如何在C#中的XML序列化过程中交替使用XML元素?

如何在C#中的XML序列化过程中交替使用XML元素?,c#,xml,serialization,xsd,C#,Xml,Serialization,Xsd,我有一个数据提供者提供给我们的XSD模式。我不能修改它。我使用XSD.exe命令行工具生成了这些类。对于一切完美的工作,我可以用C#创建我的对象,用XML序列化它,并用XSD验证它 我有一小部分问题。预期产出为: <Physical> <Class>P</Class> <Capacity>14</Capacity> <Class>J</Class>

我有一个数据提供者提供给我们的XSD模式。我不能修改它。我使用XSD.exe命令行工具生成了这些类。对于一切完美的工作,我可以用C#创建我的对象,用XML序列化它,并用XSD验证它

我有一小部分问题。预期产出为:

    <Physical>
        <Class>P</Class>
        <Capacity>14</Capacity>
        <Class>J</Class>
        <Capacity>64</Capacity>
        <Class>W</Class>
        <Capacity>1</Capacity>
        <Class>Y</Class>
        <Capacity>2</Capacity>
    </Physical>
    <Saleable Protected="true">
        <Class>P</Class>
        <Capacity>14</Capacity>
        <Class>J</Class>
        <Capacity>64</Capacity>
        <Class>W</Class>
        <Capacity>1</Capacity>
        <Class>Y</Class>
        <Capacity>2</Capacity>
    </Saleable>
在验证过程中,无论是否使用Order属性,我都会收到如下错误:

命名空间“xxx”中的元素“Physical”具有无效的子元素 命名空间“xxx”中的“类”。预期可能的要素清单: 命名空间“xxx”中的“容量”

最后,这里是XSD的一部分:

<xsd:element name="ClassA" minOccurs="0">
    <xsd:complexType>
        <xsd:all>
            <xsd:element name="Physical" minOccurs="0">
                <xsd:annotation>
                    <xsd:documentation>True, physical class A configuration</xsd:documentation>
                </xsd:annotation>
                <xsd:complexType>
                    <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                        <xsd:element name="Class" type="CabinClass.type" />
                        <xsd:element name="Capacity" type="Integer.ctype" nillable="true" />
                    </xsd:sequence>
                    <xsd:attributeGroup ref="Array.attgroup" />
                </xsd:complexType>
            </xsd:element>
            <xsd:element name="Saleable" minOccurs="0">
                <xsd:annotation>
                    <xsd:documentation>Class A configuration for sales purposes</xsd:documentation>
                </xsd:annotation>
                <xsd:complexType>
                    <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                        <xsd:element name="Class" type="CabinClass.type" />
                        <xsd:element name="Capacity" type="Integer.ctype" nillable="true" />
                    </xsd:sequence>
                    <xsd:attributeGroup ref="Array.attgroup" />
                </xsd:complexType>
            </xsd:element>
        </xsd:all>
        <xsd:attributeGroup ref="Container.attgroup" />
    </xsd:complexType>
</xsd:element>

正确,物理A类配置
用于销售目的的A类配置
我猜想这与xsd:sequence的存在有关。但正如我所说,我不想修改XSD,因为它是由数据提供者提供的,我们必须确保生成的XML完全兼容


知道如何解决这个问题吗?

简化的代码可能是:

public class Physical
{
    [XmlElement("Capacity", typeof(int))]
    [XmlElement("Class", typeof(string))]
    public object[] Items { get; set; }
}
这将确保正确的反序列化,并按照元素在数组中的放置顺序对元素进行序列化

工作版本可能如下所示:

public class Physical
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    [XmlElement("Capacity", typeof(int))]
    [XmlElement("Class", typeof(string))]
    public object[] Items
    {
        get
        {
            object[] items = new object[Class.Length * 2];
            for (int i = 0; i < items.Length; i += 2)
            {
                items[i] = Class[i / 2];
                items[i + 1] = Capacity[i / 2];
            }
            return items;
        }
        set
        {
            Class = new string[value.Length / 2];
            Capacity = new int[value.Length / 2];
            for (int i = 0; i < value.Length; i += 2)
            {
                Class[i / 2] = (string)value[i];
                Capacity[i / 2] = (int)value[i + 1];
            }
        }
    }

    [XmlIgnore]
    public string[] Class { get; set; }
    [XmlIgnore]
    public int[] Capacity { get; set; }
}
公共类物理
{
[EditorBrowsable(EditorBrowsableState.Never)]
[XmlElement(“容量”,类型(int))]
[XmlElement(“类”,类型(字符串))]
公共对象[]项
{
得到
{
object[]items=新对象[Class.Length*2];
对于(int i=0;i
int
更改为
integertype
,添加
DataType
参数


类似地,更改第二个类。

顺序与xml没有区别,但由于模式问题,因此在您的情况下,顺序非常重要。确保顺序的最佳方法是使用XDocument或XmlDocument方法编写自定义序列化。您也可以使用XmlWriter。@jdweng,谢谢您的输入。是的,他们期望这些元素有一个精确的顺序,这是很奇怪的,但不幸的是事实就是如此。对于我们来说,自定义序列化程序可能不是最好的选择,因为XSD和生成的XML文件非常庞大。我们正在尝试使用标准序列化,并仅在为简单起见需要时自定义XSD.exe生成的类。如果文件很大,则使用标准序列化会出现内存不足错误。所以您必须使用XmlReader。别无选择。
<xsd:element name="ClassA" minOccurs="0">
    <xsd:complexType>
        <xsd:all>
            <xsd:element name="Physical" minOccurs="0">
                <xsd:annotation>
                    <xsd:documentation>True, physical class A configuration</xsd:documentation>
                </xsd:annotation>
                <xsd:complexType>
                    <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                        <xsd:element name="Class" type="CabinClass.type" />
                        <xsd:element name="Capacity" type="Integer.ctype" nillable="true" />
                    </xsd:sequence>
                    <xsd:attributeGroup ref="Array.attgroup" />
                </xsd:complexType>
            </xsd:element>
            <xsd:element name="Saleable" minOccurs="0">
                <xsd:annotation>
                    <xsd:documentation>Class A configuration for sales purposes</xsd:documentation>
                </xsd:annotation>
                <xsd:complexType>
                    <xsd:sequence minOccurs="0" maxOccurs="unbounded">
                        <xsd:element name="Class" type="CabinClass.type" />
                        <xsd:element name="Capacity" type="Integer.ctype" nillable="true" />
                    </xsd:sequence>
                    <xsd:attributeGroup ref="Array.attgroup" />
                </xsd:complexType>
            </xsd:element>
        </xsd:all>
        <xsd:attributeGroup ref="Container.attgroup" />
    </xsd:complexType>
</xsd:element>
public class Physical
{
    [XmlElement("Capacity", typeof(int))]
    [XmlElement("Class", typeof(string))]
    public object[] Items { get; set; }
}
public class Physical
{
    [EditorBrowsable(EditorBrowsableState.Never)]
    [XmlElement("Capacity", typeof(int))]
    [XmlElement("Class", typeof(string))]
    public object[] Items
    {
        get
        {
            object[] items = new object[Class.Length * 2];
            for (int i = 0; i < items.Length; i += 2)
            {
                items[i] = Class[i / 2];
                items[i + 1] = Capacity[i / 2];
            }
            return items;
        }
        set
        {
            Class = new string[value.Length / 2];
            Capacity = new int[value.Length / 2];
            for (int i = 0; i < value.Length; i += 2)
            {
                Class[i / 2] = (string)value[i];
                Capacity[i / 2] = (int)value[i + 1];
            }
        }
    }

    [XmlIgnore]
    public string[] Class { get; set; }
    [XmlIgnore]
    public int[] Capacity { get; set; }
}