Mark Kadlec
Mark Kadlec

Reputation: 8440

How to check for null attributes in LinqToXML expressions?

I have a LinqToXML expression where I am trying to select distinct names based on similar attributes. The code is working great and I've put it below:

            var q = xmlDoc.Element("AscentCaptureSetup").Element("FieldTypes")
            .Descendants("FieldType")
            .Select(c => new { width = c.Attribute("Width").Value,
                                script = c.Attribute("ScriptName").Value,
                                sqlType = c.Attribute("SqlType").Value,
                                enableValues = c.Attribute("EnableValues").Value,
                                scale = c.Attribute("Scale").Value,
                                forceMatch = c.Attribute("ForceMatch").Value,
                                forceMatchCaseSensitive = c.Attribute("ForceMatchCaseSensitive").Value,
                                sortAlphabetically = c.Attribute("SortAlphabetically").Value,
                            })
            .Distinct();

The problem arises since not all the attributes are required, and if one of them is omitted, for example sortAlphabetically, I get an Object not Referenced error. Makes sense, but it there a way to alter the query to only use assign the new values if the attribute actually exists? (Thereby bypassing any null pointer errors)

Upvotes: 3

Views: 344

Answers (1)

Jon Skeet
Jon Skeet

Reputation: 1500065

Instead of using the Value property (which will blow up on a null reference), simply cast the XAttribute to string - you'll either get the value, or a null reference if the XAttribute reference is null. (XElement works the same way, and this applies to all conversions to nullable types.)

So you'd have:

.Select(c => new { 
     width = (string) c.Attribute("Width"),
     script = (string) c.Attribute("ScriptName"),
     sqlType = (string) c.Attribute("SqlType"),
     enableValues = (string) c.Attribute("EnableValues"),
     scale = (string) c.Attribute("Scale"),
     forceMatch = (string) c.Attribute("ForceMatch"),
     forceMatchCaseSensitive = (string) c.Attribute("ForceMatchCaseSensitive"),
     sortAlphabetically = (string) c.Attribute("SortAlphabetically"),
 })

Some of those attributes sound like they should actually be cast to int? or bool?, mind you...

Upvotes: 5

Related Questions