henrykodev
henrykodev

Reputation: 3084

How to get XML Attribute and Element with One Linq Query?

I have an XML document that looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <searchlayers>
    <searchlayer whereClause="ProjectNumber=a">Herbicide</searchlayer>
    <searchlayer whereClause="ProjectNumber=b">Herbicide - Point</searchlayer>
    <searchlayer whereClause="ProjectNumber=c">miscellaneous</searchlayer>
    <searchlayer whereClause="ProjectNumber=d">miscellaneous - Point</searchlayer>
    <searchlayer whereClause="ProjectNumber=e">Regrowth Control</searchlayer>
    <searchlayer whereClause="ProjectNumber=f">Regrowth Control - Point</searchlayer>
    <searchlayer whereClause="ProjectNumber=g">Tree Removal</searchlayer>
    <searchlayer whereClause="ProjectNumber=h">Tree Removal - Point</searchlayer>
    <searchlayer whereClause="ProjectNumber=i">Trimming</searchlayer>
    <searchlayer whereClause="ProjectNumber=j">Trimming - Point</searchlayer>
  </searchlayers>
</configuration>

Is it possible to write one single Linq statement to get each of the element (e.g. Herbicide, miscellaneous, Regrowth Control... etc) with its matching whereClause (e.g. for Herbicide, the where clause would be "ProjectNumber=a")?

I can write two statements separately, one to get the elements, one to get the attributes, but it would be nice to write just one Linq statement that gets both at the same time.

Thanks.

Upvotes: 1

Views: 836

Answers (4)

shree.pat18
shree.pat18

Reputation: 21757

You can use the Attributes property to get the attribute from the XML node, along with the InnerText, like so:

XmlDocument doc = new XmlDocument();
doc.LoadXml(yourxml);

XmlNodeList xlist = doc.GetElementsByTagName("searchlayer");
for(int i=0;i<xlist.Count;i++)
 {
  Console.WriteLine(xlist[i].InnerText + " " + xlist[i].Attributes["whereClause"].Value);
 }

If you must use LINQ, you could use XDocument and then return anonymous class objects consisting of the attribute and text, like so:

XDocument xdoc = XDocument.Load(yourxmlfile);
var result = xdoc.Root.Elements("searchlayers").Elements("searchlayers").Select(x => new {attr = x.Attribute("whereClause").Value, txt = x.Value});
foreach (var r in result)
 {
  Console.WriteLine(r.attr + " " + r.txt);
 }

Upvotes: 0

har07
har07

Reputation: 89325

Yes it is possible. But there are many possible data structure can be used to store list of 2 values pair, here is one example using Tuple :

XDocument doc = XDocument.Load("path_to_xml_file.xml");
List<Tuple<string, string>> result =
                doc.Root
                   .Descendants("searchlayer")
                   .Select(o => Tuple.Create((string) o, (string) o.Attribute("whereClause")))
                   .ToList();

Upvotes: 1

Johnathon Sullinger
Johnathon Sullinger

Reputation: 7414

You can use this to to select all elements matching Herbicide whose whereClause matches ProjectNumber=a

IEnumerable<XElement> result =
    from el in doc.Elements("Herbicide")
    where (string)el.Attribute("whereClause") == "ProjectNumber=a"
    select el;

Another alternative would be:

var result = doc.Descendants()
        .Where(e => e.Attribute("ProjectNumber=a") != null)
        .ToList();

Which should provide you every element whose whereClause equals "ProjectNumber=a".

Upvotes: 0

Baldrick
Baldrick

Reputation: 11840

You can create a set of anonymous objects as follows:

var result = root.Element("searchlayers")
                 .Elements("searchlayer")
                 .Select(i => 
                     new {attribute = i.Attribute("whereClause").Value, 
                          value = i.Value});

This will give a set of records, where the attributes are paired with the element values.

If you want this in query syntax, it looks like this:

var result = from el in root.Elements("searchlayers").Elements("searchlayer")
             select new {attribute = el.Attribute("whereClause").Value, 
                         value = el.Value};

Upvotes: 0

Related Questions