Reputation: 582
I have following xml which I want to Deserialize to an object.
<result>
<reporttype>2</reporttype>
<items>
<item>
<sku>0B0005</sku>
<style>0B0005.DAK.GREY</style>
<reason>Barcode cannot be moved to different SKUs</reason>
</item>
<item>
<sku>0B0006</sku>
<style>0B0006.DAK.GREY</style>
<reason>Barcode cannot be moved to different SKUs</reason>
</item>
</items>
</result>
But following code does not populate the item list, Can someone point me out what I am doing wrong here
string inputString = @"<result><reporttype>2</reporttype><items><item><sku>0B0005</sku><style>0B0005.DAK.GREY</style><reason>Barcode cannot be moved to different SKUs</reason></item><item><sku>0B0005</sku><style>0B0005.DAK.GREY</style><reason>Barcode cannot be moved to different SKUs</reason></item></items></result>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(inputString);
XmlSerializer serializer = new XmlSerializer(typeof(Result));
StringReader rdr = new StringReader(doc.InnerXml);
Result resultingMessage = (Result)serializer.Deserialize(rdr);
public enum ReportType {
[XmlEnum("0")]
InternalErrorReport,
[XmlEnum("1")]
ErrorReport,
[XmlEnum("2")]
InternalSuccessReport
}
[XmlRoot(ElementName = "result")]
public class Result {
[XmlElement(ElementName = "reporttype")]
public ReportType reportType { get; set; }
[XmlElement(ElementName = "items")]
public List<Item> items = new List<Item>();
public string error { get; set; }
public class Item {
[XmlElement(ElementName = "sku")]
string sku { get; set; }
[XmlElement(ElementName = "style")]
string style { get; set; }
[XmlElement(ElementName = "reason")]
string reason { get; set; }
}
}
Or is there a better way to do this?
Upvotes: 0
Views: 13620
Reputation: 32445
You can add two attributes for items
property - to satisfy serialization
[XmlRoot(ElementName = "result")]
public class Result
{
[XmlArray("items")]
[XmlArrayItem("item")]
public List<Item> items = new List<Item>();
}
Or just set type attribute(XmlType
) for Item class.
Then will be enough to use only XmlArray
attribute for Result.items
property. Or not using any attribute at all because name of the property match with name of the element in xml.
[XmlType("item")]
public class Item
{
[XmlElement(ElementName = "sku")]
public string sku { get; set; }
[XmlElement(ElementName = "style")]
public string style { get; set; }
[XmlElement(ElementName = "reason")]
public string reason { get; set; }
}
And of course make properties public
Upvotes: 4
Reputation: 91
As explained here you need to mark the list as XmlArray specifing also the XmlArrayItem: Deserializing nested lists with XmlSerializer
So the code becomes:
string inputString = @"<result><error>error test</error><reporttype>2</reporttype><items><item><sku>0B0005</sku><style>0B0005.DAK.GREY</style><reason>Barcode cannot be moved to different SKUs</reason></item><item><sku>0B0005</sku><style>0B0005.DAK.GREY</style><reason>Barcode cannot be moved to different SKUs</reason></item></items></result>";
XmlDocument doc = new XmlDocument();
doc.LoadXml(inputString);
XmlSerializer serializer = new XmlSerializer(typeof(Result));
object resultingMessage = null;
using (StringReader rdr = new StringReader(doc.InnerXml)) {
resultingMessage = (Result)serializer.Deserialize(rdr);
}
and the classes:
public enum ReportType {
[XmlEnum("0")]
InternalErrorReport,
[XmlEnum("1")]
ErrorReport,
[XmlEnum("2")]
InternalSuccessReport
}
[XmlRoot(ElementName = "result")]
public class Result {
[XmlElement(ElementName = "reporttype")]
public ReportType reporttype { get; set; }
[XmlArray("items")]
[XmlArrayItem("item")]
public List<Item> items { get; set; }
[XmlElement(ElementName = "error")]
public string error { get; set; }
[XmlRoot(ElementName = "items\\item")]
public class Item {
[XmlElement(ElementName = "sku")]
public string sku { get; set; }
[XmlElement(ElementName = "style")]
public string style { get; set; }
[XmlElement(ElementName = "reason")]
public string reason { get; set; }
}
}
Please, note also that I encapsulated the string reader in a using block, in order to dispose the object once the read ends.
Upvotes: 1
Reputation: 34421
Variable need to be public.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Serialization;
using System.IO;
namespace ConsoleApplication1
{
class Program
{
const string FILENAME = @"c:\temp\test.xml";
static void Main(string[] args)
{
string xml = File.ReadAllText(FILENAME);
XmlSerializer serializer = new XmlSerializer(typeof(Result));
StringReader rdr = new StringReader(xml);
Result resultingMessage = (Result)serializer.Deserialize(rdr);
}
}
public enum ReportType
{
[XmlEnum("0")]
InternalErrorReport,
[XmlEnum("1")]
ErrorReport,
[XmlEnum("2")]
InternalSuccessReport
}
[XmlRoot(ElementName = "result")]
public class Result
{
[XmlElement(ElementName = "reporttype")]
public ReportType reportType { get; set; }
public Items items { get; set; }
public string error { get; set; }
}
[XmlRoot("items")]
public class Items
{
[XmlElement(ElementName = "item")]
public List<Item> items = new List<Item>();
}
[XmlRoot("item")]
public class Item
{
[XmlElement(ElementName = "sku")]
public string sku { get; set; }
[XmlElement(ElementName = "style")]
public string style { get; set; }
[XmlElement(ElementName = "reason")]
public string reason { get; set; }
}
}
Upvotes: 2
Reputation: 481
items should be Xmlroot element and it contain XmlElement item,you have to tell when it Deserialize to object. try this :
public class Item
{
[XmlElement(ElementName = "sku")]
public string Sku { get; set; }
[XmlElement(ElementName = "style")]
public string Style { get; set; }
[XmlElement(ElementName = "reason")]
public string Reason { get; set; }
}
[XmlRoot(ElementName = "items")]
public class Items
{
[XmlElement(ElementName = "item")]
public List<Item> Item { get; set; }
}
[XmlRoot(ElementName = "result")]
public class Result
{
[XmlElement(ElementName = "reporttype")]
public string Reporttype { get; set; }
[XmlElement(ElementName = "items")]
public Items Items { get; set; }
}
Upvotes: 0