0

I have a problem parsing a XML file using Linq to XML.

My XML structure looks like:

<Module>
  <Variable Name="Variable1" Value="True" />
  <Variable Name="Variable2" Value="True" />
  <Variable Name="Variable3" Value="True" />
  </Task>
  <Task Name="Task1">
    <Variable Name="Task1Variable1" Value ="True" />
    <Variable Name=" Task1Variable2" Value ="True" />
  </Task>
  <Task Name="Task2">
    <Variable Name="Task2Variable1" Value ="True" />
    <Variable Name=" Task2Variable2" Value ="True" />
  </Task>
</Module>

What I intend to do is to get the value of each Variable Name attribute. So for the elements that are directly under the node Module it works fine with

var variables = (from cfg in _xElements.Descendants("Module").Elements("Variable")
                                       select cfg.Attribute("Name"));

The problem starts with the Variable Name attributes that are under the Task nodes because I also need the information about the Task Name.

So what I would like to get is the information about the Variable name plus the information about the Task Name that is the parent node of the variable element.

Is there a way to get this done with Linq?

ck84vi
  • 1,556
  • 7
  • 27
  • 49

3 Answers3

1

You can use parent property of XElement

var variables = (from cfg in _xElements.Descendants("Variable")
                                       select new
{
  TaskName = cfg.Parent.Name == "Task"? cfg.Parent.Attribute("Name"):null,   
  VariableAttribute = cfg.Attribute("Name")
});
Viru
  • 2,228
  • 2
  • 17
  • 28
1

The problem with your current code is since you are using Elements it is returning only the Variable which are direct child of root node. Use Descedants instead.

This query will give you the expected output:-

 var variables = (from cfg in _xElements.Descendants("Variable")
                  select cfg.Attribute("Name"));

Check difference between Elements and Descendants.

Community
  • 1
  • 1
Rahul Singh
  • 21,585
  • 6
  • 41
  • 56
0

Descendants won't work in this case. Try complete solution

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Xml.Linq;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string xml = 
                "<Module>" +
                  "<Variable Name=\"Variable1\" Value=\"True\" />" +
                  "<Variable Name=\"Variable2\" Value=\"True\" />" +
                  "<Variable Name=\"Variable3\" Value=\"True\" />" +
                  "<Task Name=\"Task1\">" +
                    "<Variable Name=\"Task1Variable1\" Value =\"True\" />" +
                    "<Variable Name=\"Task1Variable2\" Value =\"True\" />" +
                  "</Task>" +
                  "<Task Name=\"Task2\">" +
                    "<Variable Name=\"Task2Variable1\" Value =\"True\" />" +
                    "<Variable Name=\"Task2Variable2\" Value =\"True\" />" +
                  "</Task>" +
                "</Module>";

            XDocument doc = XDocument.Parse(xml);

            var results = doc.Elements("Module").Select(m => new {
                variables = m.Elements("Variable").Select(n => new {
                   name = (string)n.Attribute("Name"),
                   value = (string)n.Attribute("Value")
                }).ToList(),
                tasks = m.Elements("Task").Select(o => new {
                    name = (string)o.Attribute("Name"),
                    variables = o.Elements("Variable").Select(p => new {
                        name = (string)p.Attribute("Name"),
                        value = (string)p.Attribute("Value")
                    }).ToList()
                }).ToList()
            }).FirstOrDefault();
        }
    }
}
jdweng
  • 33,250
  • 2
  • 15
  • 20