1

I have an XML document that can have multiple children elements under another element, and I was wondering how I can get all these elements and store as an object? For example-

<?xml version="1.0" encoding="utf-8" ?>
<export>
  <order>
    <ordernumber>100</ordernumber>
    <items>
      <item>
        <name>table</name>
      </item>
      <item>
        <name>chair</name>
      </item>
    </items>
  </order>
</export>

So say I get all orders using LINQ and store in a list

var xdoc = XDocument.Load(myXMLReader);

var result = (from x in xdoc.Root.Elements()
              select new Order
              {
                  OrderNumber = (string)x.Element("OrderNumber")
              }).ToList();

What do I need to do to the above to get ALL items in an order and store in another object property such as a List or something similar? EG.

var result = (from x in xdoc.Root.Elements()
              select new Order
              {
                  OrderNumber = (string)x.Element("OrderNumber")

                  //PSUEDO CODE ADDITION
                  Items = (new { Name = itemname}).ToList()
                  // END PSUEDO CODE ADDITION

              }).ToList();
1
  • If you want to convert XML to objects, it's often simpler to just declare a type as [Serializable] and deserialize the XML into the type (or a proxy type from which you copy to the real type somehow). As far as processing the XML directly, have you looked at either the XContainer.Descendants() or XContainer.Elements() method? Commented Jan 14, 2015 at 3:51

3 Answers 3

2

I'm not entirely sure what you're trying to do. But I think it might be something like this:

var result = (from x in xdoc.Root.Elements()
              select new Order
              {
                  OrderNumber = (string)x.Element("ordernumber"),
                  Items = x.Element("items")
                           .Elements("item")
                           .Select(itemElement =>
                               new Item { Name = itemElement.Value })
                           .ToList()
              }).ToList();

In other words: for the given element, first find the one items child element, then from that element, select all of its item child elements, and finally from that collection, project to a collection of Item objects, to be materialized as a List<Item> and assigned to the Order.Items property.

(Note: you were mixing the named type Order with the anonymous type representing an item XML element; I fixed the code so that it uses named types everywhere, but you can of course use anonymous everywhere instead if you like).

Sign up to request clarification or add additional context in comments.

1 Comment

That did the trick! I used a variation of your code as I indeed have an Item object and it has more than one property, so I used "Name = itemElement.Element("name").Value" and so on
2

I think you need this:-

List<Order> orders = xdoc.Descendants("order")
                    .Select(x => new Order
                    {
                      OrderNumber = (string)x.Element("ordernumber"),
                      Items = x.Descendants("item")
                               .Select(i => new Item
                               {
                                  Name = (string)i.Element("name") }).ToList()
                               }).ToList();

Type I have used:-

public class Order
{
    public string OrderNumber { get; set; }
    public List<Item> Items { get; set; }
}

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

1 Comment

This answer works perfectly too however Peter posted first so it is fair I accept his. Thanks for the answer! +1
0

Based on the root element being named export, I thought you might be trying to serialize/de-serialize objects in your program:

[XmlRoot("export")]
public class Export
{
    [XmlElement("order")]
    public Order order {get; set;}
}

public class Order
{
    [XmlElement("ordernumber")]
    public int orderNumber { get; set; }
    [XmlArray("items"), XmlArrayItem("item")]
    public Item[] items { get; set; }
}

public class Item
{
    public string name { get; set; }
}

static void Serialize(string file, Export export)
{
    var serializer = new XmlSerializer(typeof(Export));
    using (var stream = File.Create(file))
        serializer.Serialize(stream, export);
}

static Export Deserialize(string file)
{
    var serializer = new XmlSerializer(typeof(Export));
    using (var stream = File.OpenRead(file))
        return (Export) serializer.Deserialize(stream);
}

You would call it like this:

var export = new Export
{
    order = new Order
    {
        orderNumber = 100,
        items = new[]
        {
            new Item {name = "table"},
            new Item {name = "chair"}
        }
    }
};

Serialize("exported_orders.xml", export);

and like this:

var export = Deserialize("exported_orders.xml");

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.