tags:

views:

573

answers:

3

I wondering what the "best practice" way (in C#) is to implement this xpath query with LINQ:

/topNode/middleNode[@filteringAttribute='filterValue']/penultimateNode[@anotherFilterAttribute='somethingElse']/nodesIWantReturned

I would like an IEnumerable list of the 'nodesIWantReturned', but only from a certain section of the XML tree, dependent on the value of ancestor attributes.

+2  A: 
var result = root.Elements("topNode")
                 .Elements("middleNode")
                 .Where(a => (string)a.Attribute("filteringAttribute") == "filterValue")
                 .Elements("penultimateNode")
                 .Where(a => (string)a.Attribute("anotherFilterAttribute") == "somethingElse")
                 .Elements("nodesIWantReturned");
Mehrdad Afshari
Wouldn't it be safer to use .Elements instead of .Descendants for the first three node selections? .Descendents could reach too far if the content of nodesIWantReturned has a match?
Kev
Huh, yes. Thanks. Looks like I'm sleepy :) Editing
Mehrdad Afshari
A: 

A more verbal solution:

var nodesIWantReturned = from m in doc.Elements("topNode").Elements("middleNode")
              from p in m.Elements("penultimateNode")
              from n in p.Elements("nodesIWantReturned")
              where m.Attribute("filteringAttribute").Value == "filterValue"
              where p.Attribute("anotherFilterAttribute").Value == "somethingElse"
              select n;
bruno conde
This won't work correctly. It'll throw a NullReferenceException if an element is encountered that lacks the attribute.
Mehrdad Afshari
+6  A: 

In addition to the Linq methods shown, you can also import the System.Xml.XPath namespace and then use the XPathSelectElements extension method to use your XPath query directly.

It is noted in the class that these methods are slower than 'proper' Linq-to-XML, however a lot of the time this isn't too important, and sometimes it's easier just to use XPath (it's certainly a lot terser!).

var result = doc.XPathSelectElements("your xpath here");
Greg Beech
Thank you! Great tip! Will note that this is slower.
Torbjörn Hansson