Stan
Stan

Reputation: 26511

Correct way to convert Xml to Objects?

I have very simple Xml structure that I want to convert to list of objects. My code does work but I think this is not the correct way of doing this and since I never did this I think there might be simpler way of doing what I want.

Xml example

<root>
    <item>
        <name>Item 1</name>
        <price>30.00</price>
    </item>
    <item>
        <name>Item 2</name>
        <price>55.00</price>
    </item>
</root>

Code to gather xml and create list of objects

class Program
{
    static void Main(string[] args)
    {
        List<Item> itemList = new List<Item>();
        var url = "http://xmlurl.com/xml";

        // Load xml data
        XmlDocument myXmlDocument = new XmlDocument();
        myXmlDocument.Load(url);

        // Select items and loop
        var xmlItems = myXmlDocument.SelectNodes("/root/item");
        foreach (XmlNode item in xmlItems)
        {
            var newItem = new Item();
            foreach (XmlNode i in item)
            {
                // Since I cannot query them properly I need to check every item node
                switch (i.Name)
                {
                    case "name":
                        newItem.Name = i.InnerText;
                        break;
                    case "price":
                        newItem.Price = Convert.ToDecimal(i.InnerText);
                        break;
                }
            }
            itemList.Add(newItem);
        }

        // Test it out
        foreach (var item in itemList.OrderBy(x => x.Price))
        {
            Console.WriteLine(item.Name + " | " + item.Price);
        }
        Console.ReadLine();
    }
}

class Item
{
    public string Name { get; set; }
    public decimal Price { get; set; }
}

Upvotes: 1

Views: 178

Answers (3)

Dustin Kingen
Dustin Kingen

Reputation: 21265

You can define your class:

[XmlType("item")]
public class Item
{
    [XmlElement("name")]
    public string Name { get; set; }

    [XmlElement("price")]
    public decimal Price { get; set; }
}

And then deserialize the Xml:

var xml = @"<root>
    <item>
        <name>Item 1</name>
        <price>30.00</price>
    </item>
    <item>
        <name>Item 2</name>
        <price>55.00</price>
    </item>
</root>";

List<Item> items;

var serializer = new XmlSerializer(typeof(List<Item>),
                                   new XmlRootAttribute("root"));

using(var stream = new StringReader(xml))
{
    items = (List<Item>)serializer.Deserialize(stream);
}

if(items != null)
{
    foreach(var item in items)
    {
        Console.Write(item);
    }
}

Upvotes: 0

Sam Leach
Sam Leach

Reputation: 12966

Using LINQ:

XDocument xdoc = XDocument.Load("myXml.xml");

List<Item> items = (from item in xdoc.Descendants("item")
                    select new Item {
                    Name = item.Element("name").Value,
                    Price = item.Element("price").Value
                    }).ToList();

Upvotes: 1

Ondrej Svejdar
Ondrej Svejdar

Reputation: 22084

You should use XmlSerializer, example:

Classes:

  [XmlType(TypeName="item")]
  public class Item {
    public string Name { get; set; }
    public decimal Price { get; set; }
  }

  [XmlRoot(ElementName = "root")]
  public class ItemList : List<Item> {
  }

Getting them from markup:

    const string test = @"<root>
    <item>
        <name>Item 1</name>
        <price>30.00</price>
    </item>
    <item>
        <name>Item 2</name>
        <price>55.00</price>
    </item>
</root>";

  var serializer = new XmlSerializer(typeof(ItemList));
  List<Item> result;
  using (var reader = new StringReader(test)) {
    result = (List<Item>)serializer.Deserialize(reader);
  }

Upvotes: 0

Related Questions