Friday, April 29, 2011

LINQ to XML Newbie Question

is there a better way to do this kind of thing:

var filter = new CashFilters();
var element = XElement.Parse(request.OuterXml);

var productId = element.Elements("ProductId").Select(el => el);

if (productId.Count() == 1)
    filter.ProductId = Convert.ToInt32(productId.Single().Value);
From stackoverflow
  • Well, the Select(el => el) isn't doing you any good to start with.

    I suggest you use SingleOrDefault:

    var productId = element.Elements("ProductId").SingleOrDefault();
    if (productId != null)
        filter.ProductId = Convert.ToInt32(productId.Value);
    

    Note that that handles the case where there are no ProductId elements, but will throw an exception if there's more than one. If that's actually a valid case, then your current code (without the redundant Select call) is reasonable.

    EDIT: You could get away from this with:

    var productId = element.Elements("ProductId")
                           .Select(elt => elt.Value)
                           .SingleOrDefault();
    filter.ProductId = Convert.ToInt32(productId ?? filter.ProductId.ToString());
    

    But that's pretty ghastly ;)

    Basically you've got a condition - you only want to set the ProductId if it's specified. An "if" statement is the generally accepted way of conditionally executing code :)

    There are alternatives:

    filter.ProductId = productId == null 
                       ? filter.ProductId 
                       : int.Parse(productId);
    

    If you don't mind filter.ProductId being set to 0 if there's no ID specified, then you can just use:

    filter.ProductId = Convert.ToInt32(element.Elements("ProductId")
                                              .Select(elt => elt.Value)
                                              .SingleOrDefault());
    

    (due to the way that Convert.ToInt32 returns 0 when passed a null argument.)

    AWC : so there's no way to get ride of the null check? great book by the way :)
  • Do you REALLY need to do this in Linq to Xml? The Xml DOM approach seems much more reasonable to me.

    Have you considered the pure Xml approach?

        XmlDocument doc = new XmlDocument();
        doc.LoadXml(request.OuterXml);
    
        var node = doc.SelectSingleNode("//ProductId[1]");
        if (node != null)
            filter.ProductId = Convert.ToInt32(node.InnerText);
    
    Jon Skeet : Personally I prefer the LINQ to XML approach - less scary (uncompiled) string stuff to go wrong. Simply using Elements("ProductId").SingleOrDefault() does the same as the XPath expression, but with less to know IMO.

0 comments:

Post a Comment