Dr. Dobb's is part of the Informa Tech Division of Informa PLC

This site is operated by a business or businesses owned by Informa PLC and all copyright resides with them. Informa PLC's registered office is 5 Howick Place, London SW1P 1WG. Registered in England and Wales. Number 8860726.


Channels ▼
RSS

Web Development

Comparing LINQ-to-XML with XPath


Finding Children

Another thing you might want to do is find the value of child elements. To trim up the code for this example, you can use the XML in Listing One without the namespace. The LINQ-to-XML uses imperative code and the XElement object chained together to request children, and the XPath query uses a value that looks a lot like a file path statement (see Listing Four).

private static void FindChild()
{
   const string filename = "..\\..\\CurrentStats.xml";
   XElement xml = XElement.Load(filename);
   XElement child1 = xml.Element("Player")

   Console.WriteLine(child1);
   Console.ReadLine();
   // XPath expression using System.Xml.Linq capabilities
   XElement child2 = xml.XPathSelectElement("Player/Statistics/AverageAmount-
Lost");
   Console.WriteLine(child2);
   Console.ReadLine();
}
Listing Four: Selecting a Child Element with LINQ to XML and Then an XPath Query

The second half of Listing Three uses an XPath query, Player/Statistics/AverageAmountLost. Because both parts are using capabilities and classes in the System.Xml.Linq namespace, you can easily blend queries and chained XElement calls in the same code block.

Finding Siblings

Methods like XElement.ElementsAfterSelf request sibling elements. The first half of Listing Five requests the next sibling element, and the second half uses an XPath query to perform the same task.

private static void FindSibling()
{
  const string filename = "..\\..\\CurrentStats.xml";
  XElement xml = XElement.Load(filename);
  XElement child1 = xml.Element("Player")

  XElement sibling1 = child1.ElementsAfterSelf().First();
  Console.WriteLine(sibling1);
  Console.ReadLine();
  XElement child2 = xml.XPathSelectElement("Player/Statistics/AverageAmountWon");
  XElement sibling2 = child2.XPathSelectElement("following-sibling::*");
  Console.WriteLine(sibling2);
  Console.ReadLine();
}
Listing Five: LINQ-to-XML and XPath Supporting Requesting Siblings, Children, and Parents

The XPath query (or XQuery) following-sibling::* illustrates where I think XPath becomes less intuitive. The path statement Player/Statistics/AverageAmount looks like a path; following-sibling::* begs for a trip to the help documentation. However, because XPath is a W3C (World Wide Web Consortium) open standard, it is unlikely they will change it for us. (Note: XPath and XSLT are W3C open standards determined by a committee (or consortium). LINQ-to-XML is a proprietary part of the .NET Framework. This difference alone might discourage "open standards" wonks from using LINQ to XML, but something that can be gleaned by intuition gets higher marks than open standards for standards sake with me.)

Filtering Elements

Filtering XML documents with LINQ queries and where clauses was demonstrated. Listing Six demonstrates how to query the Player element with LINQ-to-XML and a LINQ query, and the second half of the code shows the equivalent behavior using an XQuery. Again, the LINQ query seems more intuitive than the XQuery Player[@Name='Player 1'].

private static void FilterOnAttribute()
{
  const string filename = "..\\..\\CurrentStats.xml";
  XElement xml = XElement.Load(filename);
  XElement player1 =
    (from elem in xml.Elements("Player")
    where elem.Attribute("Name").Value == "Player 1"
    select elem).First();
  Console.WriteLine(player1);
  XElement player2 = xml.XPathSelectElement("Player[@Name='Player 1']");
  Console.WriteLine(player2);
  Console.ReadLine();
}
Listing Six: Filtering with LINQ and XQuery

In the XQuery Player[@Name='Player 1'], Player is the node and the bracketed @Name part refers to the Name attribute and its value. The correct statement looks like an index operation, but perhaps from a C# programmer's point of view Player.Name = 'Player 1' would be more intuitive. This lends itself to my argument that if you are comfortable with C#, then using LINQ-to-XML and method calls might be significantly easier to pick up than XPath queries.

Without an exhaustive comparison of XPath and LINQ-to-XML, you get the idea. LINQ-to-XML is going to be XDocument and XElement method calls and XPath is going to be queries defined by that standard; the XPath query syntax is distinct from C# code. At some level, you will be able to do more with less typing if you use XPath just as you can do some very advanced comparisons with regular expressions with less typing. The decision matrix that helps you decide which technology to use depends on your experience and the experience of the members of your team.


Related Reading


More Insights






Currently we allow the following HTML tags in comments:

Single tags

These tags can be used alone and don't need an ending tag.

<br> Defines a single line break

<hr> Defines a horizontal line

Matching tags

These require an ending tag - e.g. <i>italic text</i>

<a> Defines an anchor

<b> Defines bold text

<big> Defines big text

<blockquote> Defines a long quotation

<caption> Defines a table caption

<cite> Defines a citation

<code> Defines computer code text

<em> Defines emphasized text

<fieldset> Defines a border around elements in a form

<h1> This is heading 1

<h2> This is heading 2

<h3> This is heading 3

<h4> This is heading 4

<h5> This is heading 5

<h6> This is heading 6

<i> Defines italic text

<p> Defines a paragraph

<pre> Defines preformatted text

<q> Defines a short quotation

<samp> Defines sample computer code text

<small> Defines small text

<span> Defines a section in a document

<s> Defines strikethrough text

<strike> Defines strikethrough text

<strong> Defines strong text

<sub> Defines subscripted text

<sup> Defines superscripted text

<u> Defines underlined text

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task. However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

 
Disqus Tips To upload an avatar photo, first complete your Disqus profile. | View the list of supported HTML tags you can use to style comments. | Please read our commenting policy.