Omer
Omer

Reputation: 10174

XML Deserialization Array

I have a class. I want to deserialize XML file into this class.

public partial class Form1 : Form
{
    public string xmlFile;

    public Form1()
    {
        InitializeComponent();
        xmlFile = "Sample.xml";
    }

    [Serializable]
    public class Application
    {
        public string AppName;
        public string UpdateDetail;
    };

    [Serializable]
    public class Applications
    {
        [XmlElement]
        public Application[] Application;
    };



    [Serializable]
    public class Pmsp_Update
    {
        public string OldVersion;
        public string NewVersion;
        public Applications Applications;
    };

    private void btnRead_Click(object sender, EventArgs e)
    {
        XmlReader reader = XmlReader.Create(xmlFile);
        XmlSerializer ser = new XmlSerializer(typeof(Pmsp_Update));
        Pmsp_Update pu;
        using (reader = XmlReader.Create(xmlFile))
        {
            pu = (Pmsp_Update)ser.Deserialize(reader);
        }
    }
}

And here is the XML:

<Pmsp_Update>
  <OldVersion>v4.0.0</OldVersion>
  <NewVersion>v4.0.1</NewVersion>
  <Applications>
    <Application>
      <AppName>SampleApp</AppName>
      <UpdateDetail>sample</UpdateDetail>
     </Application>
  </Applications>
</Pmsp_Update>

I want to ask about attributes. I only used [Serializable] attribute and I can get the class. I don't use any [XmlElement] attribute and this didn't cause any error except one.

If I use like this I can populate the array but:

        [Serializable]
        public class Applications
        {
            [XmlElement]
            public Application[] Application;
        };

If I use like this I can't populate the array:

[Serializable]
public class Applications
{
    public Application[] Application;
};

So, my question is this: I am not using [XmlElement] for fields and everything works well but I can't populate the array. Why couldn't I populate the array when I don't use [XmlElement] although I can populate the fields?

Upvotes: 1

Views: 1588

Answers (1)

MarcinJuraszek
MarcinJuraszek

Reputation: 125610

The easiest way to check what's going on is to create object of your class and serialize it to XML. This is what I get:

Without [XmlElement]

<?xml version="1.0" encoding="utf-16"?>
<Pmsp_Update xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <OldVersion>v4.0.0</OldVersion>
  <NewVersion>v.4.0.1</NewVersion>
  <Applications>
    <Application>
      <Application>
        <AppName>Test</AppName>
        <UpdateDetail>test</UpdateDetail>
      </Application>
    </Application>
  </Applications>
</Pmsp_Update>

With [XmlElement]

<?xml version="1.0" encoding="utf-16"?>
<Pmsp_Update xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <OldVersion>v4.0.0</OldVersion>
  <NewVersion>v.4.0.1</NewVersion>
  <Applications>
    <Application>
      <AppName>Test</AppName>
      <UpdateDetail>test</UpdateDetail>
    </Application>
  </Applications>
</Pmsp_Update>

As you can see, only the second one matches your input XML, and that's why you cannot deserialize yout XML without [XmlElement] attribute - because your XML document does not match your class structure.

Empty XmlElement on top of array property prevent serializer from expecting additional element to handle array elements. That behavior is described on MSDN: XmlElementAttribute Class

If you apply the XmlElementAttribute to a field or property that returns an array, the items in the array are encoded as a sequence of XML elements.

In contrast if an XmlElementAttribute is not applied to such a field or property, the items in the array are encoded as a sequence of elements, nested under an element named after the field or property. (Use the XmlArrayAttribute and XmlArrayItemAttribute attributes to control how an array is serialized.)

You can achieve the same by changing your class structure to

public class Application
{
    public string AppName;
    public string UpdateDetail;
};

public class Pmsp_Update
{
    public string OldVersion;
    public string NewVersion;
    public Application[] Applications;
};

<Applications> element will be added automatically for array property, so you don't need Applications class.

Upvotes: 2

Related Questions