tags:

views:

79

answers:

1

I'm just learning Linq, and stuck on what I hope is fairly simple. My xml document is like:

<?xml version="1.0" encoding="utf-8"?>
<XDOC>
    ...
    <ItemsDetail>
        <Item name="Item1">
            <data1>
                <Data type="classA">55</Data>
                <Data type="classB">66</Data>
            </data1>
            <data2>
                <Data type="classA">77</Data>
                <Data type="classB">88</Data>
            </data2>
        </Item>
    </ItemsDetail>
</XDOC>

So I load my XML above into an XDocument type and then query the

var query = from p in ILSXml.Elements("XDOC").Elements("ItemsDetail").Elements("Item")
            select p;

Then I run a foreach on on the query.

foreach (var record in query)
{
    Console.WriteLine("Name: {0}", record.Attribute("Name").Value);
    Console.WriteLine("Data1 ClassA: {0}", record.Element("data1").Element("Data").Attribute("classA").Value);
}

So the line:

Console.WriteLine("Data1 ClassA: {0}", record.Element("data1").Element("Data").Attribute("classA").Value);

does not work which, is what I was pretty much expecting. Do I have to run another series of queries or run some inline anonymous methods?

Oh and please don't comment on the xml, it's not mine, I just have to work with it.

+2  A: 

I assume that you're trying to get the value 55? You can use the First method to find the first "Data" element with a "type" attribute value of "classA".

record.Element("data1")
      .Elements("Data")
      .First(data => data.Attribute("type").Value == "classA")
      .Value

Note that the above solution is quite fragile. Any change to the structure of the input xml document is likely to cause a null reference exception.

You can also query XML documents using the more compact XPath query language. XPath has the ability to filter elements using a simple expression wrapped in square brackets. Your code would then look something like this:

foreach (var record in ILSXml.XPathSelectElements("XDOC/ItemsDetail/Item"))
{
    Console.WriteLine("Name: {0}",
        record.Attribute("name").Value);
    Console.WriteLine("Data1 ClassA: {0}",
        record.XPathSelectElement("data1/Data[@type='classA']").Value);
}
Nathan Baulch
That works, similar to what I was looking at just now, though missing the .First.Is there a more recommended way to work with such an xml document?
Coding Monkey
If you can get your hands on an XSD (XML schema document) that describes your document then I would definitely look at generating real classes and using standard XML serialization.
Nathan Baulch