Alistair McIntyre
Alistair McIntyre

Reputation: 414

XML reading repeating child elements with same name as parent c#

I have xml in format below:

<rows>
   <rows>
      <primitiveValue>000</primitiveValue>
   </rows>
   <rows>
      <primitiveValue>58316</primitiveValue>
   </rows>
   <rows>
   <primitiveValue>133083.0</primitiveValue>
   </rows>
</rows>
<rows>
  <rows>
    <primitiveValue>001</primitiveValue>
  </rows>
  <rows>
    <primitiveValue>66018</primitiveValue>
  </rows>
  <rows>
    <primitiveValue>172546.0</primitiveValue>
  </rows>
</rows>

I need to split the data per parent element of rows, but don't know how to do this.

I've tried the code below, but this loops through every instance of rows and causes duplication.

        string Values = "";

        foreach (XElement element in xDoc.Descendants("rows"))
        {

            foreach (XElement childElement in element.Descendants("rows").Elements("primitiveValue"))
            {

                Values = Values + "," + childElement.Value.ToString();

            }


        }

Can someone help please?

Upvotes: 2

Views: 7513

Answers (2)

Sergey Berezovskiy
Sergey Berezovskiy

Reputation: 236188

Very simple with System.Xml.XPath.Extensions:

var values = xdoc.XPathSelectElements(@"//rows/rows/primitiveValue").Select(v => (double)v);
string result = String.Join(",", values);

Values will be IEnumerable<double> containing values of primitiveValue elements. And result will be concatenated string of all values. BTW you are missing root element in your xml.

UPDATE

IEnumerable<string> result = 
             xdoc.Root.Elements("rows")
                 .Select(r => String.Join(",", r.Descendants("primitiveValue")
                                                .Select(v => (double)v)));

This will return sequence of strings, each of string will contain concatenated values of inner rows. If you need raw strings instead of double values, then cast value nodes to string.

Upvotes: 0

Jesse Carter
Jesse Carter

Reputation: 21147

Descendants will find all nodes with the name that you are looking for regardless of how far down the XML tree that they are. Try experimenting with something like this:

foreach (XElement element in xDoc.Children("rows"))
        {
            foreach (XElement childElement in element.Descendants("rows").Elements("primitiveValue"))
            {
                Values = Values + "," + childElement.Value.ToString();
            }
        }

The key is that using Children should only return nodes that are directly below the root element as opposed to searching the entire structure of the XML document for matching elements.

Upvotes: 1

Related Questions