Let’s say you wanted to select the parts for a Lenovo X60 laptop from the following XML.
<Root> <Manufacturer Name="Lenovo="> <Model Name="X60=" > <Parts> <!-- ... --> </Parts> </Model> <Model Name="X200="> <!-- ... --> </Model> </Manufacturer> <Manufacturer Name="...=" /> <Manufacturer Name="...=" /> <Manufacturer Name="...=" /> <Manufacturer Name="...=" /> </Root>
If you know LINQ to XML, you might load up an XDocument and start the party with a brute force approach:
var parts = xml.Root .Elements("Manufacturer") .Where(e => e.Attribute("Name").Value == "Lenovo") .Elements("Model") .Where(e => e.Attribute("Name").Value == "X60") .Single() .Element("Parts");
But, the code is ugly and makes you long for the days when XPath ruled the planet. Fortunately, you can combine XPath with LINQ to XML. The System.Xml.XPath namespace includes some XPath specific extension methods, like XPathSelectElement:
string xpath = "Manufacturer[@Name='Lenovo']/Model[@Name='X60']/Parts"; var parts = xml.Root.XPathSelectElement(xpath);
Now the query is a bit more readable (at least to some), but let’s see what we can do with extension methods.
static class ComputerManufacturerXmlExtensions { public static XElement Manufacturer(this XElement element, string name) { return element.Elements("Manufacturer") .Where(e => e.Attribute("Name").Value == name) .Single(); } public static XElement Model(this XElement element, string name) { return element.Elements("Model") .Where(e => e.Attribute("Name").Value == name) .Single(); } public static XElement Parts(this XElement element) { return element.Element("Parts"); } }
Now, the query is short and succinct:
var parts = xml.Root.Manufacturer("Lenovo").Model("X60").Parts();
Combine an XSD file with T4 code generation and you’ll have all the extension methods you’ll ever need for pretty XML queries...