2

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?

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • Can you change the xml at all? If so, it would behoove you to make it `` instead of calling everything rows. – Ryan Gates Jan 17 '13 at 20:08
  • nah i can't as it comes from a google analytics api. it is returned automatically in JSON and then i convert it to XML as I want to use a process i have already set up to import xml per row into a SQL Server DB – Alistair McIntyre Jan 18 '13 at 10:52
  • If that is the case, I suggest you look into [JSON.net](http://stackoverflow.com/q/814001/299327) for converting from JSON to XML rather than rolling your own. – Ryan Gates Jan 18 '13 at 14:17
  • i've already used JSON.net to convert it from JSON to this in XML. That above fragment part of the converted XML document – Alistair McIntyre Jan 18 '13 at 14:20

2 Answers2

1

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.

Jesse Carter
  • 20,062
  • 7
  • 64
  • 101
0

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.

Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459
  • i need to split the primitivevalues into rows though In this example there are 3 values per row. I working on an automated process where the number of values per row will vary also – Alistair McIntyre Jan 18 '13 at 11:18
  • @AlistairMcIntyre sorry, didn't get what you are trying to do. With your sample xml this code returns string with all values `0,58316,133083,1,66018,172546` – Sergey Berezovskiy Jan 18 '13 at 11:36