Reputation: 718
I have something similar to the XML below. I'm parsing it using Linq in C#, and it works great, until we get to a product which doesn't have a type
.
<productList>
<product>
<type>
<colour>red</colour>
</type>
<name>First</name>
</product>
<product>
<name>Second</name>
</product>
</productList>
I'm trying to access the colour
element under type
, but when the code reaches a product
which doesn't have the type
element, I get the "Object reference not set to an instance of an object" error.
Here's the code I'm using to access it at the moment. Things have got a little complicated with the attempts I've tried to solve this.
productColour = products.Element("type").Descendants().FirstOrDefault() == null ? string.Empty : products.Element("type").Descendants().FirstOrDefault().Value,
I know the colour
element is always the first underneath type
, so I can use .FirstOrDefault()
, but I still get the same error using this code.
Can anyone point me towards the right direction? I've also tried casting to a string, and also having: ?? " "
at the end, all to no avail so far.
Edit: Thanks to @anthony-pegram, it looks like the issue is that I'm always trying to grab the descendants, even if the parent element doesn't exist. So it looks like I need to check the parent element before grabbing the child - can anyone point me in a direction for this?
Upvotes: 4
Views: 1301
Reputation: 3091
Have you thought of using an Attribute instead?
<productList>
<product type="color-red">
<name>First</name>
</product>
<product type="none">
<name>Second</name>
</product>
</productList>
No chance of returning a null variable, as the type attribute can have a default string value. I also think this is more tidy, but that's personal preference.
You could also do <product color="red" />
etc.
Upvotes: 0
Reputation: 1575
Elements() wiil return an IEnumerable. If the element does not exist, IEnumerable will just be empty and calling Elements again on it will not product a null reference exception. The code below should pull the colour from under a product\type element without throwing a null reference exception. If colour or type do not exist, it will return a null.
(string)product.Elements("type").Elements("colour").FirstOrDefault()
Upvotes: 3
Reputation: 116138
I would use XPath here
var xDoc = XDocument.Parse(xml);
var colour = xDoc.XPathSelectElement("//product/type/colour");
if(colour!=null)
{
var val = colour.Value;
}
Upvotes: 0