views:

1116

answers:

3

I am trying to load multiple elements with the same name from XML into a class using deserialisation in C#. Everything in my example loads fine but the array elements (Element3) are not populated.

Code:

class Program
{
    static void Main(string[] args)
    {
        FileStream file = new FileStream("service.xml", FileMode.Open);

        if (file != null)
        {
            XmlSerializer serializer = new XmlSerializer(typeof(Service));
            Service service = (Service)serializer.Deserialize(file);
        }
    }
}

public class Service
{
    public bool Element1;
    public string Element2;
    public string[] Element3;
}

XML:

<Service>
    <Element1>true</Element1>
    <Element2>Text 1</Element2>
    <Element3>Text 2</Element3>
    <Element3>Text 3</Element3>
</Service>
+2  A: 

The reason that your array isn't loading is because, as far as .NET XML Serialization is concerned, you're not trying to read an array. An array would be represented something like:

<Element3Array>
    <ArrayElement>Text 2</ArrayElement>
    <ArrayElement>Text 3</ArrayElement>
</Element3Array>

You'll need to either change the format of the source XML or create a custom XML Serializer for your class to deal with your situation.

Justin Niessner
+2  A: 

I think your xml is wrong. Logically, an array is serialized like this:

<Element3>
    <string>Text 2</string>
    <string>Text 3</string>
</Element3>

So, your xml must have this format:

<Service>
    <Element1>true</Element1>
    <Element2>Text 1</Element2>
    <Element3>
        <string>Text 2</string>
        <string>Text 3</string>
    </Element3>
</Service>

Edit: Added a example to unserialize this xml if you cannot change the format. The code below is not tested.

Your class Service must derived from IXmlSerializable:

public class Service : IXmlSerializable
{
    public System.Xml.Schema.XmlSchema  GetSchema()
    {
        return null;
    }

    public void  ReadXml(System.Xml.XmlReader reader)
    {
        List<string> element3 = new List<string>();

        while (reader.Read())
        {
     if (reader.Name == "Element1" && reader.NodeType == XmlNodeType.Element)
     {
      Element1 = Convert.ToBoolean(reader.ReadString());
     }
     else if (reader.Name == "Element2" && reader.NodeType == XmlNodeType.Element)
     {
      Element2 = reader.ReadString();
     }
     if (reader.Name == "Element1" && reader.NodeType == XmlNodeType.Element)
     {
      element3.Add(reader.ReadString());
     }
        }

        Element3 = element3.ToArray();
    }

    public void  WriteXml(System.Xml.XmlWriter writer)
    {
        writer.WriteStartElement ("Service"); 

        writer.WriteStartElement ("Element1"); 
     writer.WriteString(Element1.ToString());
        writer.WriteEndElement();

        writer.WriteStartElement ("Element2"); 
     writer.WriteString(Element2.ToString());
        writer.WriteEndElement();

        foreach (string ele in Element3)
        {
     writer.WriteStartElement ("Element3"); 
     writer.WriteString(ele);
     writer.WriteEndElement();
        }

        writer.WriteEndElement();
    }
}
Francis B.
It isn't my XML - it's just what I have to work with.
Nat Ryall
@Kelix: Well if you cannot receive a xml correctly formatted for your class, you will need to create a custom Xml Serializer as suggested by Justin.
Francis B.
+3  A: 

Try putting [XmlElement] on Element3.

John Saunders
This worked! Thanks!
Nat Ryall
@John: Wow so simple :). I didn't know that was possible just with this attribute.
Francis B.
It's well worthwhile to read the docs on the attributes, and even to create little examples for yourself to see how they work. Sooner or later you'll need them.
John Saunders