2

When I have a repeater on a xsd:sequence

for example: <xsd:sequence minOccurs="1" maxOccurs="unbounded">

This would be the matching xml:

<Element>
  <name>e1</name>
  <number>n1</number>
  <details>i1</details>
  <name>e2</name>
  <number>n2</number>
  <details>i2</details>
  <name>e3</name>
  <number>n3</number>
  <details>i3</details>
</Element>

on the other side, when I have a repeater on the element:

<xsd:sequence>
    <xsd:element name="name" type="xsd:token" minOccurs="1" maxOccurs="unbounded"/>
    <xsd:element name="number" type="xsd:token" minOccurs="1" maxOccurs="unbounded"/>
    <xsd:element name="details" type="xsd:token" minOccurs="1" maxOccurs="unbounded"/>
</xsd:sequence>

the matching xml would be:

<Element>
  <name>e1</name>
  <name>e2</name>
  <name>e3</name>
  <number>n1</number>
  <number>n2</number>
  <number>n3</number>
  <details>i1</details>
  <details>i2</details>
  <details>i3</details>
</Element>

But when I'm converting the following xsd file to a C# class (using )

<xsd:element name="Element" type="ElementType"/>
  <xsd:complexType name="ElementType">
    <xsd:sequence minOccurs="1" maxOccurs="unbounded">
      <xsd:element name="name" type="xsd:token"/>
      <xsd:element name="number" type="xsd:token"/>
      <xsd:element name="details" type="xsd:token"/>
    </xsd:sequence>
  </xsd:complexType>

generated C# class:

public partial class ElementType{

    private string[] nameField;

    private string[] numberField;

    private string[] detailsField;

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

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

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

I get this xml (generated based on the class with XmlSerializer)

<Element>
  <name>e1</name>
  <name>e2</name>
  <name>e3</name>
  <number>n1</number>
  <number>n2</number>
  <number>n3</number>
  <details>i1</details>
  <details>i2</details>
  <details>i3</details>
</Element>

Is there a way to generate the correct xml? Or if this is just the way Microsofts XmlSerializer works, how do I need to modify the C# class to get the correct result?

nulldevops
  • 396
  • 3
  • 15
  • Microsoft serializes in the order of the properties in the class. So if you have an array string[] name the names array in xml will appear in sequence. – jdweng May 02 '19 at 19:09
  • @jdweng I get that, but it's a fixed requirement I have here. So my question is: is there a way to get the expected result? Probably there is no way around editing the generated XML... Because I guess there is no equivalent element in C# to do that. – nulldevops May 03 '19 at 05:52

1 Answers1

0

Use a Customer Serialzier :

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.Xml.Linq;
using System.Xml.Schema;

namespace ConsoleApplication111
{
    class Program
    {
        const string INPUT_FILENAME = @"c:\temp\test.xml";
        const string OUTPUT_FILENAME = @"c:\temp\test1.xml";
        static void Main(string[] args)
        {
            XmlReader reader = XmlReader.Create(INPUT_FILENAME);
            XmlSerializer serializer = new XmlSerializer(typeof(ElementType));
            ElementType elementType = (ElementType)serializer.Deserialize(reader);

            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            XmlWriter writer = XmlWriter.Create (OUTPUT_FILENAME, settings);
            serializer.Serialize(writer, elementType);
        }
    }
    [XmlRoot("Element")]
    public partial class ElementType : IXmlSerializable
    {

        private string[] nameField;

        private string[] numberField;

        private string[] detailsField;

        /// <remarks/>
        [XmlElement(ElementName = "name", DataType = "token")]
        public string[] name
        {
            get
            {
                return this.nameField;
            }
            set
            {
                this.nameField = value;
            }
        }

        /// <remarks/>
        [XmlElement(ElementName = "number", DataType = "token")]
        public string[] number
        {
            get
            {
                return this.numberField;
            }
            set
            {
                this.numberField = value;
            }
        }

        /// <remarks/>
        [XmlElement(ElementName = "details", DataType = "token")]
        public string[] details
        {
            get
            {
                return this.detailsField;
            }
            set
            {
                this.detailsField = value;
            }
        }

        public void ReadXml(XmlReader reader)
        {
            XElement elementType = XElement.Load(reader);
            nameField = elementType.Elements("name").Select(x => (string)x).ToArray();
            numberField = elementType.Elements("number").Select(x => (string)x).ToArray();
            detailsField = elementType.Elements("details").Select(x => (string)x).ToArray();

        }
        public void WriteXml(XmlWriter writer)
        {
            int count = nameField.Count();
            XElement element = new XElement("Element");
            for(int i = 0; i < count; i++)
            {
                element.Add(new XElement("name", name[i]));
                element.Add(new XElement("number", number[i]));
                element.Add(new XElement("details", detailsField[i]));

            }
            writer.WriteRaw(element.ToString());
        }


        public XmlSchema GetSchema()
        {
            return (null);
        }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20