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(); }
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(); }
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(); }
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.