尝试获取xml标记的值时,我遇到了一个nullexception问题,该标记位于可能不存在的子树下。
扩展处理程序在现有子树上找不到标记时效果很好,但在子树中查找不存在的标记时似乎无法处理。
在这种情况下,子树是summaryData,可能存在或不存在,并且尝试获取addressLine1是它不处理null
的地方,我得到错误
发生System.NullReferenceException,Message = Object reference not not 设置为对象的实例。
这是xml,为了清晰起见,但结构是正确的:
<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>
我的C#代码是:
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"))
};
我处理null的扩展方法是:
public static string GetElementValue(this XElement element)
{
if (element != null)
{
return element.Value;
}
else
{
return string.Empty;
}
}
任何帮助都会受到赞赏,因为当子树不存在时我无法理解为什么会失败。
答案 0 :(得分:2)
摘要数据可能存在也可能不存在
这就是原因。在您进行嵌套调用时,您必须对它们进行无效检查所有。
其中任何一个都可以为null:
c.Element("summaryData").Element("serviceAddress").Element("addressLine1")
没有复杂的条件,就没有漂亮的方法:
street_address = c.Element("summaryData") != null
? c.Element("summaryData").Element("serviceAddress") != null
? GetElementValue(c.Element("summaryData").Element("serviceAddress").Element("addressLine1"))
: string.Empty
: string.Empty;
答案 1 :(得分:1)
如果summaryDate
元素不存在则
c.Element("summaryData").Element("serviceAddress").Element("addressLine1")
会抛出NullReferenceException
,因为您尝试在空引用(Element()
)上调用c.Element("summaryData")
答案 2 :(得分:1)
如前所述,您的异常是由于您正在传递多个嵌套查询
c.Element("summaryData").Element("serviceAddress").Element("addressLine1")
是写作的等价物:
var x1 = c.Element("summaryData");
var x2 = x1.Element("serviceAddress")
var x3 = x2.Element("addressLine1")
因此,如果c
,x1
或x2
中的任何一个为空,那么您将获得NullReferenceException
。
使用多个空检查的纯LINQ
解决方案的一种可能替代方法是使用XPath
来构建表达式。
使用XPath
,而不是在每个级别进行空检查,您可以改为编写表达式:
street_address = GetElementValue(c.XPathSelectElement("/summaryData/serviceAddress/addressLine1"))
这将评估整个表达式,如果它不完整,它将返回null
,但不会像纯LINQ查询那样抛出异常。