views:

556

answers:

1

I want to deserialize xml like this:

<Product>
    <Classification>
        <NewClassification>1</NewClassification>
        <NewClassification>2</NewClassification>
        <NewClassification>3</NewClassification>
        <OldClassification>A</OldClassification>
        <OldClassification>B</OldClassification>
    </Classification>
</Product>

My classes are:

public class Product
{
    public Classification Classification { get; set; }
}

public class Classification
{
    [XmlArrayItem(typeof(int), ElementName = "NewClassification")]
    public List<int> NewClassificationList { get; set; }
    [XmlArrayItem(typeof(int), ElementName = "OldClassification")]
    public List<int> OldClassificationList { get; set; }
}

Why this code is wrong?

+2  A: 

Apart from the "int literal" issue commented on by "Bears will eat you" above, you can't serialize your class in the way you want with what you've got (at least I can't think of a way to do it) without resorting to custom serialisation (e.g. implementing IXmlSerializable or some other method).

Your basic problem is that you have two seperate collections in Classification, which you want to appear as a single collection.

The IXmlSerialization route is pretty simple though. Just implement it as follows on your Classification class, and you'll get the desired result.

public class Classification : IXmlSerializable
{
    public List<int> NewClassificationList { get; set; }
    public List<string> OldClassificationList { get; set; }

    #region IXmlSerializable Members

    public void WriteXml(System.Xml.XmlWriter writer)
    {
        foreach (var item in NewClassificationList)
        {
            writer.WriteElementString("NewClassification", item.ToString());
        }

        foreach (var item in OldClassificationList)
        {
            writer.WriteElementString("OldClassification", item.ToString());
        }
    }

    public System.Xml.Schema.XmlSchema GetSchema()
    {
        throw new NotImplementedException();
    }

    public void ReadXml(System.Xml.XmlReader reader)
    {
        throw new NotImplementedException();
    }

    #endregion
}

[Added ReadXml implementation]

ReadXml can be implemented as follows:

 public void ReadXml(System.Xml.XmlReader reader)
    {
        var product = new Product();

        product.Classification = new Classification
                                     {
                                         NewClassificationList = new List<int>(),
                                         OldClassificationList = new List<string>()
                                     };

        reader.ReadStartElement("Classification");

        while (reader.NodeType != System.Xml.XmlNodeType.EndElement)
        {
           switch (reader.Name)
           {
               case "NewClassification":
                   product.Classification.NewClassificationList.Add(reader.ReadElementContentAsInt());
                   break;
               case "OldClassification":
                   product.Classification.OldClassificationList.Add(reader.ReadElementContentAsString());
                   break;
               default:
                   throw new NotSupportedException("Unsupported node: " + reader.Name);
           } 
        }

        reader.ReadEndElement();
    }
Rob Levine
I don't insist that these classifications have to be List<int> or List<string>. It might be a custom class as well.
jlp
OK. In any case, the custom serialization code above should produce exactly the output you have described in the question
Rob Levine
How should I implement ReadXml() ? I basically want to deserialize XML into custom some class.
jlp
Sample ReadXml implementation added
Rob Levine
My example become more complicated so I'll ask separate question. http://stackoverflow.com/questions/1880983/how-to-deserialize-xml-with-multiple-nested-items
jlp