ragmn
ragmn

Reputation: 505

XML Parsing using LINQ to fetch attribute along with contents

Here is my XML,

<content id = "C1">
<paragraph >
      <Info />
      <contentValue>Content1</contentValue>
</paragraph>

<paragraph>
      <Info />
      <contentValue>Content2</contentValue>
</paragraph>
<content>

<content id = "C2">
<paragraph >
      <Info />
      <contentValue>Content3</contentValue>
</paragraph>

<paragraph>
      <Info />
      <contentValue>Content4</contentValue>
</paragraph>

<paragraph>
      <Info />
      <contentValue>Content5</contentValue>
</paragraph>
<content>

I need to parse through each of <content> tags and fetch the values of <contentvalue> tags and store it in a List.

I'm using following code but, values of <contentvalue> tags are concatinated like 'Content1Content2'

var xdoc = XDocument.Load(path);
var Contents = xdoc.Descendants("content").Select(c => (string)c).ToArray();

Upvotes: 0

Views: 108

Answers (3)

Andrei V
Andrei V

Reputation: 7496

If you don't want your <contentValue>s to be grouped by the <content> tag, just try:

V1

var Contents = xdoc.Descendants("contentValue").Select(c => (string)c).ToArray();

or V2

var Contents = xdoc.Root.XPathSelectElements("content/paragraph/contentValue")
       .Select(x => x.Value).ToList();

NOTE that for using the V2 solution you need to add a reference to the System.Xml.XPath namespace.


(This next section represents a different solution, for a different but similar case, provided for reference purposes) Otherwise, if you need to get the values grouped by the <content> tag, you could try:

var grouped = xdoc.Descendants("contentValue")
       .Select(x => new { PNode = x.Ancestors("content")
       .FirstOrDefault().Attribute("id").Value, CNode = x.Value })
       .GroupBy(x => x.PNode).ToDictionary(x => x.Key, y => y.ToList());

This then can be iterated as follows:

foreach (var group in grouped)
{
     Console.WriteLine("content id = " + group.Key);
     foreach (var singleCValue in group.Value)
     {
          Console.WriteLine(singleCValue.CNode);
     }
}

Upvotes: 1

Nitin Varpe
Nitin Varpe

Reputation: 10694

I guess your tags are not well formed. You can do something like this.

 XDocument doc = XDocument.Load(path);

            IList<string> list=new List<string>();

            IEnumerable<XElement> contentElements = doc.Descendants("content");//this get all "content" tags
            IEnumerable<XElement> contentValueElements = contentElements.Descendants("contentValue");//this get all "contentValue" tags

            foreach (XElement i in contentValueElements)
            {

                    list.Add(i.Value);
            }

Upvotes: 0

Siva Charan
Siva Charan

Reputation: 18064

Couple of things I noticed:

  1. Your XML is not in a correct format
  2. You are trying to select Content node and render it as string, which is wrong

XML:

<root>
    <content id="C1">
        <paragraph>
            <Info/>
            <contentValue>Content1</contentValue>
        </paragraph>
        <paragraph>
            <Info/>
            <contentValue>Content2</contentValue>
        </paragraph>
    </content>
    <content id="C2">
        <paragraph>
            <Info/>
            <contentValue>Content3</contentValue>
        </paragraph>
        <paragraph>
            <Info/>
            <contentValue>Content4</contentValue>
        </paragraph>
        <paragraph>
            <Info/>
            <contentValue>Content5</contentValue>
        </paragraph>
    </content>
</root>

Code:

var Contents = xdoc.Descendants("content").Descendants("paragraph").Select(i => i.Element("contentValue").Value).ToList();

Above code exactly selects contentValue node under paragraph.

Upvotes: 1

Related Questions