JOO
JOO

Reputation: 77

XML to Linq Element in Descendants getting object ref error when selecting by attribute

I have an xml doc that I am parsing to see whether an element with a particular attribute exists or not.

When I do

item.Descendants().Elements("nameValue");

I can see a bunch of results and when I drill down I can even see the attribute

Let's say I have a nameValue node that looks like this:

<nameValue idref="myIDRef" name="elementName"/>

I've tried 2 different ways to find this element by the idref and both return object ref errors. I'm sure this is extremely simple but I've been staring at this for so long that I'm really stuck

item.Descendants().Select(a => a.Element("nameValue")).Where(b => b.Attribute("idref").Value == "myIDRef");
item.Descendants().Elements("nameValue").Single(a => a.Attribute("idref").Value == "myIDRef");

Neither of the above work

EDIT: I think I've figured out why it is working. My collection of nameValue elements has hundreds of items, not all of them have an "idref" attribute which is why it was throwing my object reference error even though that particular attribute did exist in the collection.

My solution to this was to not use Linq and use XPathSelectElements instead

var nameValueArr = element.XPathSelectElements("descendant::nameValue[@idref='myIDRef']");

Upvotes: 1

Views: 162

Answers (2)

Magnetron
Magnetron

Reputation: 8553

You could use

var el = item.Descendants("nameValue")
  .FirstOrDefault(x=>x.Attribute("idref")?.Value=="myIDRef");

Single will return an error if there is more than one element, while FirstOrDefault return the first element or null if there are no elements.

After I read your edit, You could use the null-condicional operator (?.) before Value, like in the code above. If there is no "idref" attribute, it will return null, otherwise it evaluates the Value.

Upvotes: 0

ocuenca
ocuenca

Reputation: 39326

I saw your update now, you can still use linq to xml to get the result you are expecting:

var result= item.Descendants("nameValue")
                .Where(e=>(string)e.Attribute("idref")=="myIDRef");

Casting will return null if the attribute is missing, so, you are save of errors, because you will compare null with "myIDRef" in case of attribute doesn't exist in the element

Upvotes: 1

Related Questions