C# XElement扩展方法的问题

C# XElement扩展方法的问题,c#,xml,linq,extension-methods,C#,Xml,Linq,Extension Methods,我使用下面的代码从XML文件中提取信息。但如果节点不存在,则会出现NullReferenceException错误。我认为使用LINQ不应该发生这种情况。但在这方面,我对LINQ和XML非常陌生。因此,我添加了从中找到的扩展方法。但我仍然得到了错误。有人能告诉我我错过了什么吗 using System; using System.Text; using System.Windows.Forms; using System.Linq; using System.Xml.Linq; public

我使用下面的代码从XML文件中提取信息。但如果节点不存在,则会出现NullReferenceException错误。我认为使用LINQ不应该发生这种情况。但在这方面,我对LINQ和XML非常陌生。因此,我添加了从中找到的扩展方法。但我仍然得到了错误。有人能告诉我我错过了什么吗

using System;
using System.Text;
using System.Windows.Forms;
using System.Linq;
using System.Xml.Linq;

public static class XElementExtensionMethod
{
    public static string ElementValueNull(this XElement element)
    {
        if (element != null)
        {
            return element.Value;
        }
        else
        {
            return string.Empty;
        }
    }
}

namespace XMLReader
{
    public partial class frmMain : Form
    {
        public frmMain()
        {
            InitializeComponent();
        }

        private void frmMain_Load(object sender, EventArgs e)
        {
            string file = @"c:\users\jim\desktop\XMLData - Copy.xml";
            XElement doc = XElement.Load(file);
            StringBuilder sb = new StringBuilder();

            var nodes = from node in doc.Elements("ClaimsSvcRs").Elements("ClaimDownloadRs")
                    select new
                    {
                        ClaimProbableAmount = (string)node.Element("ClaimsDownloadInfo").Element("ClaimsOccurrence").Element("ProbableIncurredAmt").Element("Amt").ElementValueNull()
                    };

        foreach (var node in nodes)
        {
            sb.Append("AMOUNT = ").Append(node.ClaimProbableAmount);
            MessageBox.Show(sb.ToString());
        }
    }
}
}

问题几乎肯定不在
ElementValueNull
中。。。这是因为较早的
元素
调用之一返回null。您正在调用一个实例方法(),这是一个非常普通的实例方法-如果在null引用上调用它,它将抛出一个异常,就像任何其他实例方法一样

避免这种情况的一种方法是反复使用
元素
,这样您将得到一个空序列,而不是空引用。最后使用
FirstOrDefault
获取单个
XElement
引用或
null

此外:

  • 当您只有一个属性时,使用匿名类型没有任何好处。只需选择字符串本身
  • 在循环的每次迭代中调用
    ToString()
    时,使用
    StringBuilder
    没有任何好处
我会将您的查询写为:

var amounts = doc.Elements("ClaimsSvcRs").Elements("ClaimDownloadRs")
                 .Select(x => (string) x.Elements("ClaimsDownloadInfo")
                                        .Elements("ClaimsOccurrence")
                                        .Elements("ProbableIncurredAmt")
                                        .Elements("Amt")
                                        .FirstOrDefault() ?? "");

(请注意,不需要扩展方法-如果输入为
null
,则显式转换为
string
将返回
null
,然后空合并操作符将注意使用
而不是
null
)问题几乎肯定不在
ElementValueNull
中。。。这是因为较早的
元素
调用之一返回null。您正在调用一个实例方法(),这是一个非常普通的实例方法-如果在null引用上调用它,它将抛出一个异常,就像任何其他实例方法一样

避免这种情况的一种方法是反复使用
元素
,这样您将得到一个空序列,而不是空引用。最后使用
FirstOrDefault
获取单个
XElement
引用或
null

此外:

  • 当您只有一个属性时,使用匿名类型没有任何好处。只需选择字符串本身
  • 在循环的每次迭代中调用
    ToString()
    时,使用
    StringBuilder
    没有任何好处
我会将您的查询写为:

var amounts = doc.Elements("ClaimsSvcRs").Elements("ClaimDownloadRs")
                 .Select(x => (string) x.Elements("ClaimsDownloadInfo")
                                        .Elements("ClaimsOccurrence")
                                        .Elements("ProbableIncurredAmt")
                                        .Elements("Amt")
                                        .FirstOrDefault() ?? "");

(请注意,不需要扩展方法-如果输入为
null
,则显式转换为
string
将返回
null
,然后空合并操作符将注意使用
而不是
null
)问题几乎肯定不在
ElementValueNull
中。。。这是因为较早的
元素
调用之一返回null。您正在调用一个实例方法(),这是一个非常普通的实例方法-如果在null引用上调用它,它将抛出一个异常,就像任何其他实例方法一样

避免这种情况的一种方法是反复使用
元素
,这样您将得到一个空序列,而不是空引用。最后使用
FirstOrDefault
获取单个
XElement
引用或
null

此外:

  • 当您只有一个属性时,使用匿名类型没有任何好处。只需选择字符串本身
  • 在循环的每次迭代中调用
    ToString()
    时,使用
    StringBuilder
    没有任何好处
我会将您的查询写为:

var amounts = doc.Elements("ClaimsSvcRs").Elements("ClaimDownloadRs")
                 .Select(x => (string) x.Elements("ClaimsDownloadInfo")
                                        .Elements("ClaimsOccurrence")
                                        .Elements("ProbableIncurredAmt")
                                        .Elements("Amt")
                                        .FirstOrDefault() ?? "");

(请注意,不需要扩展方法-如果输入为
null
,则显式转换为
string
将返回
null
,然后空合并操作符将注意使用
而不是
null
)问题几乎肯定不在
ElementValueNull
中。。。这是因为较早的
元素
调用之一返回null。您正在调用一个实例方法(),这是一个非常普通的实例方法-如果在null引用上调用它,它将抛出一个异常,就像任何其他实例方法一样

避免这种情况的一种方法是反复使用
元素
,这样您将得到一个空序列,而不是空引用。最后使用
FirstOrDefault
获取单个
XElement
引用或
null

此外:

  • 当您只有一个属性时,使用匿名类型没有任何好处。只需选择字符串本身
  • 在循环的每次迭代中调用
    ToString()
    时,使用
    StringBuilder
    没有任何好处
我会将您的查询写为:

var amounts = doc.Elements("ClaimsSvcRs").Elements("ClaimDownloadRs")
                 .Select(x => (string) x.Elements("ClaimsDownloadInfo")
                                        .Elements("ClaimsOccurrence")
                                        .Elements("ProbableIncurredAmt")
                                        .Elements("Amt")
                                        .FirstOrDefault() ?? "");
(请注意,不需要扩展方法-如果输入为
null
,则显式转换为
string
将返回
null
,然后空合并操作符将注意使用
而不是
null

这是一个问题:

ClaimProbableAmount = (string)node.Element("ClaimsDownloadInfo").Element("ClaimsOccurrence").Element("ProbableIncurredAmt").Element("Amt").ElementValueNull()
由于您使用的是
Element()
,因此您可能会面临获得NRE的风险
Element()
返回命名元素的第一个实例或null。你从兔子洞里跳得太远了

有多种方法可以解决此问题,可以更改除最后一个调用之外的所有调用,以使用
Elements()
。这一次,如果它们不存在,它将只返回一个空集合。或者使用其他方法,例如等效的xpath查询。

这是一个问题:

ClaimProbableAmount = (string)node.Element("ClaimsDownloadInfo").Element("ClaimsOccurrence").Element("ProbableIncurredAmt").Element("Amt").ElementValueNull()
由于您使用的是
Element()
,因此您可能会面临获得NRE的风险
Element()
返回命名元素的第一个实例