Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Linq and XDocument, can I get all the child elements under parent tag?

I have an XML

<data>
  <summary>
    <account curr_desc='USD' acct_nbr='123' net='1000.00' />
    <account curr_desc='USD' acct_nbr='456' net='2000.00' />
  </summary>
  <details>
    <accounts>
      <account acct_nbr="123" curr="USD">
        <activity color='False' settle_date='02 Jul 2010' amt='580.00' />
        <activity color='True' settle_date='09 Jul 2010' amt='420.00' />
      </account>
      <account acct_nbr="456" curr="USD">
        <activity color='True' settle_date='12 Dec 2010' amt='1500.00' />
        <activity color='True' settle_date='19 Dec 2010' amt='500.00' />
      </account>
    </accounts>
  </details>
</data>

Using Linq and XDocument, I can extract "summary" information but how can I extract "account" information under "summary" tag?

XDocument XMLDoc = XDocument.Load("testdata.xml");
XElement accounts = (from xml2 in XMLDoc.Descendants("summary")
                    select xml2).FirstOrDefault();

How can I specify something like "summary/account" so that it returns me all the elements under <summary>? Note, that I have <account> under <detail><accounts>, I only want the elements under summary tag.

like image 374
Sri Reddy Avatar asked Apr 25 '11 16:04

Sri Reddy


2 Answers

You should use the Elements method:

var accounts = doc.Root.Elements("summary").Elements("account");

Or, alternatively, XPathSelectElements, which in this case is simpler:

var accounts = doc.XPathSelectElements("/data/summary/account");

In this instance you can also use Descendants, as Andrew Barber suggested, but in general you should only do this when you really want to find all descendants with a given name, and not just immediate children. Otherwise your code does a lot of searching that it doesn't need to, and may return elements you don't want it to.

like image 69
Robert Rossney Avatar answered Nov 09 '22 08:11

Robert Rossney


var accountSummaryElems = 
   XMLDoc.Element("summary").Elements("account");

This gives you a collection of the account elements under the summary element. You can then iterate them to get the values.

EDITED to use the same pattern you were; I call First() instead of FirstOrDefault() because that code won't run anyway if the "account" element is not found.

Then you have the right idea with iterating over the collection returned.

like image 32
Andrew Barber Avatar answered Nov 09 '22 08:11

Andrew Barber