XPath Extensions is cool!


I’m been using XDocument and it’s API for some time, but I wasn’t aware of an XPath Extensions in the .NET Framework. Thanks to my co-worker Lucy, she’s shared with me some good tips and in turn I’m sharing it with you.

Consider this XML.

<?xml version="1.0" encoding="utf-8" ?>
<Order>
 <Product id="1" name="Nexus 5">
 <Price>400.00</Price>
 <Qty>1</Qty>
 </Product>
 <Product id="5" name="Wireless Charger">
 <Price>50.00</Price>
 <Qty>1</Qty>
 </Product>
</Order>

This would have been typically how I would dig into the XML to find certain data using XDocument, in a safe way of course.

public string FindPriceForProduct(XDocument xDoc, string productName)
{
    XElement orderElement = xDoc.Element("Order");
    if (orderElement != null)
    {
        XElement productElement = orderElement.Elements("Product")
                                .FirstOrDefault(product=> product.Attribute("name") != null
                                            && product.Attribute("name").Value == productName);
        if (productElement != null)
        {
            XElement priceElement = productElement.Element("Price");
            return priceElement != null ? priceElement.Value : string.Empty;
        }
    }
    return string.Empty;
}

public decimal FindTotalCost(XDocument xDoc)
{
    XElement orderElement = xDoc.Element("Order");
    if (orderElement != null)
    {
        IEnumerable productPrices = orderElement.Elements("Product")
                                        .SelectMany(product => product.Elements("Price"))
                                        .Select(price => decimal.Parse(price.Value));
        return productPrices.Sum();
    }
    return 0;
}

As you can see from the code above, it’s defensive and unsightly, even with the Linq extensions. With XPath Extensions, all you need is to add using System.Xml.XPath and new extension methods will be available on XDocument object. Let’s rewrite the code above with XPath Extensions.

using System;
using System.Xml.Linq;
using System.Xml.XPath;

public string FindPriceForProduct(XDocument xDoc, string productName)
{
    string xpath = string.Format("/Order/Product[@name='{0}']/Price", productName);
    XElement productElement = xDoc.XPathSelectElement(xpath);
    return productElement != null ? productElement.Value : string.Empty;
}

public decimal FindTotalCost(XDocument xDoc)
{
    object prices = xDoc.XPathEvaluate("sum(/Order//Product/Price/text())");
    return prices != null ? Convert.ToDecimal(prices) : 0;
}

This new code is much neater, and there isn’t any need to check for nulls. If any part of the xpath expression has invalid nodes, the result will be null. There is only one method call, and not to mention the cool XPath conditions and functions you can use with the extension method. This greatly simplifies unnecessary complexity with code.

Here are some XPath examples you can use. Enjoy.

Posted in C#. Tags: , . Leave a Comment »

Leave a comment