3

尝试获取可能不存在的子树下的 xml 标记的值时,我遇到了 nullexception 问题。

扩展处理程序在无法在现有子树上找到标记时工作得很好,但在查找不存在的子树中的标记时似乎无法处理。

在这种情况下,子树是 summaryData,它可能存在也可能不存在,并且尝试获取 addressLine1 是它无法处理的地方null,我得到了错误

System.NullReferenceException 发生,Message=Object 引用未设置为对象的实例。

这是 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;
        }
    }

任何帮助将不胜感激,因为我不明白为什么当子树不存在时它会失败。

4

3 回答 3

2

汇总数据可能存在也可能不存在

这就是为什么。当您嵌套调用时,您必须对它们全部进行空检查。

其中任何一项都可能为空:

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;
于 2013-02-28T14:36:20.887 回答
1

如果summaryDate元素不存在,则

c.Element("summaryData").Element("serviceAddress").Element("addressLine1")

会抛出 aNullReferenceException因为你试图调用Element()一个空引用 ( c.Element("summaryData"))

于 2013-02-28T14:34:31.053 回答
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 查询那样抛出异常。

于 2013-03-01T00:45:39.223 回答