如何在C#中的XML序列化期间替换XML元素?

时间:2017-06-02 22:56:49

标签: c# xml serialization xsd

我有一个由数据提供者提供给我们的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>

正如您所看到的,物理和可密封备用的子元素(即类,然后是容量,然后是类,然后是容量等)。

这是由XSD.exe生成的类的代码:

public partial class ClassA
{
    private string[] classField;

    private Integerctype[] capacityField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Class", DataType = "token")]
    public string[] Class
    {
        get
        {
            return this.classField;
        }
        set
        {
            this.classField = value;
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute("Capacity", IsNullable = true)]
    public Integerctype[] Capacity
    {
        get
        {
            return this.capacityField;
        }
        set
        {
            this.capacityField = value;
        }
    }
}

序列化后我收到的输出:

<Physical>
    <Class>P</Class>
    <Class>J</Class>
    <Class>W</Class>
    <Class>Y</Class>
    <Capacity>14</Capacity>
    <Capacity>64</Capacity>
    <Capacity>1</Capacity>
    <Capacity>2</Capacity>
</Physical>
<Saleable>
    <Class>P</Class>
    <Class>J</Class>
    <Class>W</Class>
    <Class>Y</Class>
    <Capacity>14</Capacity>
    <Capacity>64</Capacity>
    <Capacity>1</Capacity>
    <Capacity>2</Capacity>
</Saleable>

正如您所看到的,我们失去了Class和Capacity之间的交替......

我尝试使用XmlElementAttribute的Order属性:Class属性用Order = 1装饰,而Capacity属性用Order = 2装饰,但它没有帮助。例如:

[System.Xml.Serialization.XmlElementAttribute("Class", DataType = "token", Order = 1)]
public string[] Class

在验证过程中,无论是否有Order属性,我都会收到如下错误:

  

命名空间“xxx”中的“Physical”元素具有无效的子元素   命名空间'xxx'中的'Class'。预期的可能元素列表:   命名空间'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>

我的猜测是它与xsd:sequence的存在有关。但正如我所说,我不想修改由数据提供者提供的XSD,我们必须确保我们生成的XML完全兼容。

知道如何解决这个问题?

1 个答案:

答案 0 :(得分:1)

简化代码可能是这样的:

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; }
}

int更改为Integerctype,添加DataType参数。

同样,改变第二节课。