That line of code has a lot of assumptions about the underlying data. For example, this:
e.Element(P + "Item").Attribute(P + "Description").Value
That segment of code assumes that:
e
is guaranteed to contain an element matchingP + "Item"
- That element is guaranteed to contain an attribute matching
P + "Description"
These assumptions are throughout that line. So if data is ever encountered which doesn't meet these assumptions, .Element()
or .Attribute()
might return null
, in which case the next .
(such as in .Value
) would be trying to dereference a null
value, resulting in that error.
To add some null value checking, you can either separate it into multiple lines of code or put it all in-line. The readability and maintainability of either approach is up to you. For example, with this segment:
new XAttribute("LineNumber", e.Element(P + "ID").Value)
You might add some error checking like this:
new XAttribute("LineNumber",
(e == null ? string.Empty :
(e.Element(P + "ID") == null ? string.Empty :
e.Element(P + "ID").Value)))
I could see where that could be pretty unreadable. You can perhaps eliminate the first check, assuming that e
itself will never be null
. But your other segments are still going to have a handful of nested checks.
To break it apart, you'd have to loop over the values instead of using a single LINQ statement. A structure like this:
var InvoiceLines = new List<XElement>();
foreach (var e in Document.Root.Element(P + "InvoiceLines").Elements(P + "InvoiceLine"))
{
// build an XElement object from e and add it to the list
}
This isn't 100% identical, since it eager-loads the entire set. So you might also separate the loop itself into another method which returns an IEnumerable<XElement>
and use yield return
to not have to eager-load the whole thing. It's up to you.
Come to think of it, your initial selector of data also makes assumptions:
Document.Root.Element(P + "InvoiceLines").Elements(P + "InvoiceLine")
You might want to add null
checking there as well, just in case you ever receive data which doesn't match those predicates.