Null处理的扩展方法不适用于xq的linq

时间:2013-02-28 14:30:23

标签: c# xml linq-to-xml

尝试获取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;
        }
    }

任何帮助都会受到赞赏,因为当子树不存在时我无法理解为什么会失败。

3 个答案:

答案 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")

因此,如果cx1x2中的任何一个为空,那么您将获得NullReferenceException

使用多个空检查的纯LINQ解决方案的一种可能替代方法是使用XPath来构建表达式。

使用XPath,而不是在每个级别进行空检查,您可以改为编写表达式:

street_address = GetElementValue(c.XPathSelectElement("/summaryData/serviceAddress/addressLine1"))

这将评估整个表达式,如果它不完整,它将返回null,但不会像纯LINQ查询那样抛出异常。