Reputation: 115
I have an nullexception issue when trying to get the value of an xml tag, which is under a subtree that may not be there.
The extension handler works great when it can't find a tag on an existing subtree, but seems to not be able to handle when looking for a tag in a subtree that doesn't exist.
In this case, the subtree is summaryData, which may or not be there, and trying to get addressLine1 is where it doesn't handle the null
, and I get the error
System.NullReferenceException occurred, Message=Object reference not set to an instance of an object.
Here is the xml, cut down for clarity, but structure is correct:
<record>
<accounts>
<account >
</account >
</accounts>
<summaryData>
<Date>2013-02-04</Date>
<address >
<city>Little Rock</city>
<postalCode>00000</postalCode>
<state>AR</state>
<addressLine1>Frank St</addressLine1>
</serviceAddress>
</summaryData>
</record>
My C# code is:
xmlDoc.Descendants("account")
//select (string)c.Element("account") ;
select new
{
//this works fine
Stuffinxml = c.Element("stuffinxml").Value,
//this field may not be there, but the handler handlers the exception correctly here when it as the correct root (account)
otherstuff = CustXmlHelp.GetElementValue(mR.Element("otherstuff")),
//this is the problem, where the summaryData root does not exist (or moved somewhere else)
street_address = GetElementValue(c.Element("summaryData").Element("serviceAddress").Element("addressLine1"))
};
My extension method to handle a null is:
public static string GetElementValue(this XElement element)
{
if (element != null)
{
return element.Value;
}
else
{
return string.Empty;
}
}
Any help would be appreciated, as I can't see why it fails when the subtree does not exist.
Upvotes: 3
Views: 298
Reputation: 8741
As had been stated, your exception is due to the fact that you are passing multiple nested queries
c.Element("summaryData").Element("serviceAddress").Element("addressLine1")
is the equivalant of writing:
var x1 = c.Element("summaryData");
var x2 = x1.Element("serviceAddress")
var x3 = x2.Element("addressLine1")
So if any of c
, x1
, or x2
are null, you are going to get a NullReferenceException
.
One possible alternative to a pure LINQ
solution using multiple null checks, is to use XPath
to build the expression.
With XPath
, rather than doing a null check at every level, you can instead write your expression:
street_address = GetElementValue(c.XPathSelectElement("/summaryData/serviceAddress/addressLine1"))
This will evaluate the entire expression and if it does not exist in its entirety, it will return null
, but will not thrown an exception like your pure LINQ query.
Upvotes: 1
Reputation: 56429
The summary data may or may not be there
That's why. As you're nesting calls, you'll have to null check them all.
Any one of these could be null:
c.Element("summaryData").Element("serviceAddress").Element("addressLine1")
Without a complex conditional, there's not a nice way around it:
street_address = c.Element("summaryData") != null
? c.Element("summaryData").Element("serviceAddress") != null
? GetElementValue(c.Element("summaryData").Element("serviceAddress").Element("addressLine1"))
: string.Empty
: string.Empty;
Upvotes: 2
Reputation: 152521
If the summaryDate
element does not exist then
c.Element("summaryData").Element("serviceAddress").Element("addressLine1")
will throw a NullReferenceException
because you're trying to call Element()
on a null reference (c.Element("summaryData")
)
Upvotes: 1