1

The content of an XDocument is the XML below.

I'd like to get a List(), see at the end of this message.

<myXml>
  <myDatas code="01">
    <myVar name="myvar" value="A" />
    <myData name="A" value="A1" />
    <myData name="B" value="B1" />
  </myDatas>
  <myDatas code="02">
    <myVar name="myvar" value="B" />
    <myData name="A" value="A2" />
    <myData name="D" value="D2" />
  </myDatas>
</myXml>

public class MyData
{
    public string MainCode { get; set; }
    public string Code { get; set; }
    public string Value { get; set; }
}

I'd like a List() this content should be like this :

new MyData { MainCode = "01"; Code = "A"; Value = "A1" };
new MyData { MainCode = "01"; Code = "B"; Value = "B1" };
new MyData { MainCode = "02"; Code = "A"; Value = "A2" };
new MyData { MainCode = "02"; Code = "D"; Value = "D2" };
TheBoubou
  • 19,487
  • 54
  • 148
  • 236

1 Answers1

8

Sure - so you need something like this:

var query = from datas in doc.Root.Elements("myDatas")
            let code = (string) datas.Attribute("code")
            from data in datas.Elements("myData")
            select new MyData {
                MainCode = code,
                Code = (string) data.Attribute("name"),
                Value = (string) data.Attribute("value"),
            };

var list = query.ToList();

Note the multiple from clauses to flatten the results.

Another alternative would have been to just find all the "leaf" elements and fetch the code part from the parent:

var query = from data in doc.Descendants("myData")
            select new MyData {
                MainCode = (string) data.Parent.Attribute("code"),
                Code = (string) data.Attribute("name"),
                Value = (string) data.Attribute("value"),
            };

var list = query.ToList();

EDIT: If your document uses namespaces, that's easy too:

XNamespace ns = "http://the-uri-of-the-namespace";
var query = from data in doc.Descendants(ns + "myData")
            ...

This uses the XName operator +(XNamespace, string) overloaded operator.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Could you check my update Jon. With the sample, the first XML code, it's ok, but not with the one in the update (od course I adapted the name attribute) – TheBoubou Feb 27 '13 at 07:06
  • @Kris-I: Well does your document *actually* have a `myXml` root tag or not? And what happened to the Value part? You say it's "not ok" with the second XML - what happens? (You've given two pretty different documents, with two different sets of expected results. I'm not surprised my original answer didn't work with the second document...) – Jon Skeet Feb 27 '13 at 07:10
  • Your code work, but I get an exception in 2 cases : 1. when myxml node has a namespace 2. when an attribute value has a "é" (data are in french) exception : Invalid character in the given encoding – TheBoubou Feb 27 '13 at 07:43
  • @Kris-I: Namespaces are easy in LINQ to XML - I'll add an example in my answer. For the encoding piece, that sounds like your XML data is invalid... you need to make sure the encoding used in the document matches the declaration, with UTF-8 being a default if it's not explicitly stated. (I'd recommend UTF-8.) – Jon Skeet Feb 27 '13 at 09:21