Capturing non-existent XML nodes before an "object not installed" error

I have something similar to the XML below. I parse it with Linq in C # and it works fine until we get to a product that does not have type .

 <productList> <product> <type> <colour>red</colour> </type> <name>First</name> </product> <product> <name>Second</name> </product> </productList> 

I am trying to access the colour element in type , but when the code reaches product that does not have a type element, I get an "Object" link that is not set to an instance of the object error.

Here is the code I'm using to access it at the moment. All this was a little complicated with the attempts that I was trying to solve.

 productColour = products.Element("type").Descendants().FirstOrDefault() == null ? string.Empty : products.Element("type").Descendants().FirstOrDefault().Value, 

I know that the colour element is always the first under type , so I can use .FirstOrDefault() , but still getting the same error using this code.

Can someone point me in the right direction? I also tried casting on a string as well with: ?? " " ?? " " at the end, everything still hasn’t helped.

Edit: Thanks to @ anthony-pegram, it seems like the problem is that I always try to capture the descendants, even if the parent element does not exist. So it seems like I need to check the parent before capturing the child - can anyone point me in the direction for this?

+4
source share
3 answers

The wiil elements () return an IEnumerable. If the element does not exist, IEnumerable will simply be empty and will call Elements again on it, will not handle a null-referenced exception. The code below should pull the color from the product \ type element without throwing a null reference exception. If the color or type does not exist, it will return zero.

 (string)product.Elements("type").Elements("colour").FirstOrDefault() 
+3
source

I would use XPath here

 var xDoc = XDocument.Parse(xml); var colour = xDoc.XPathSelectElement("//product/type/colour"); if(colour!=null) { var val = colour.Value; } 
0
source

Have you considered using the attribute?

 <productList> <product type="color-red"> <name>First</name> </product> <product type="none"> <name>Second</name> </product> </productList> 

It is not possible to return a null variable because the type attribute may have a default string value. I also think this is more neat, but it is a personal preference.

You can also do <product color="red" /> etc.

0
source

Source: https://habr.com/ru/post/1447012/


All Articles