tags:

views:

27

answers:

2

I’m using Linq to extract values from some XML. Shown below is a simplified example to show the problem I’m having. The following code works fine on the XML shown below. The problem I have is when the “groupBy” section is missing. Because when it’s missing “Data.Element("groupBy").Element("property)” fails because “Data.Element("groupBy")” will be null. Is it possible to modify my Linq statement to allow it to provide a default or should it be approached in a different way?

var e = (from Data in theXML.Descendants("exportFile")
 select new Export
 {    
     OutputFileName = Data.Element("outputFileName") != null ? (string)Data.Element("outputFileName") : "",
     GroupByProperty =  Data.Element("groupBy").Element("property") != null ? (string)Data.Element("groupBy").Element("property") : ""
 }).First();

<exportFile>
    <outputFileName>output.xml</outputFileName>
    <groupBy>
        <property>DeviceId</property>
    </groupBy>
</exportFile>
+2  A: 

You can already make it slightly nicer than it is using the null coalescing operator. However, to cope with the groupby element being missing is harder:

select new Export
{    
    OutputFileName = (string) Data.Element("outputFileName") ?? "",
    GroupByProperty = Data.Element("groupBy") == null ? ""
           : (string) Data.Element("groupBy").Element("property") ?? ""
}).First();

The conversion to string just returns null if the element reference is null.

An alternative would be:

GroupByProperty = 
    (string) Data.Elements("groupBy").Elements("property").FirstOrDefault() ?? ""

That uses the extension method which allows you to call Elements on an IEnumerable<XElement>... so that will (lazily) evaluate a sequence of every property element under a groupBy element under Data, then take the first of them if any exist, then apply the string conversion.

Jon Skeet
I think the OP was saying the groupBy element did not exist in the XML. Wouldn't this still fail if that was the case?
Justin Niessner
@Justin: Yeah, I misread - but fixed now :)
Jon Skeet
@Jon - Interesting. I didn't realize that you could use FirstOrDefault() when you had a null value upstream in the call chain. Learn something new every day.
Justin Niessner
Thanks Jon, that did the trick.
Retrocoder
A: 

You could simply add an additional check in the statement (and clean things up a bit using the null coalescing operator):

GroupByProperty = Data.Element("groupBy") != null ? 
    (Data.Element("groupBy").Element("property") ?? "") : "";
Justin Niessner