XMLlinq查询列出了第一个元素,但不是全部

本文关键字:全部 元素 第一个 查询 XMLlinq | 更新日期: 2023-09-27 18:00:45

我有一个XML文件,我将其解析为其元素,并创建一个自定义对象模块的列表。

XDocument kobra = XDocument.Load(new StringReader(results.OuterXml));
XNamespace ns = "#RowsetSchema";
var kobraNodeList = from s in kobra.Descendants(ns + "row")
                    select new Module
                    {
                         id = s.Attribute("ows_ID").Value,
                         name = s.Attribute("ows_Title").Value,
                         sourceFile = s.Attribute("ows_Source_x0020_Message_x0020_File_").Value,
                         scope = Scope.KOBRA,
                         component = string.Empty
                    };

这是我的模块结构:

public struct Module
{
    public string name;
    public Scope scope;
    public string component;
    public int wordCound;
    public string id;
    public string sourceFile;
}

代码运行良好,但当我试图将var kobraNodeList转换为模块列表时,事情变得很奇怪,我在AddRange行得到了一个System.NullReferenceException

this.moduleList = new List<Module>;
this.moduleList.AddRange(kobraNodeList);

在尝试调试时,我注意到虽然kobraNodeList.Count()也返回System.NullReferenceException,但kobraNodeList.Any()返回truekobraNodeList.First()返回一个具有所需数据的完全有效且正确的Module结构。

XML文件是有效的,如果我用以下内容替换linq查询:

var kobraNodeList = from s in kobra.Descendants(ns + "row")
                    select  s;

我得到了一个有效的XElement列表,我可以Count() ok。有人能解释我怎么了吗?顺便说一句,我用的是.NET 3.5。

XMLlinq查询列出了第一个元素,但不是全部

看起来kobra.Descendants中的一个(或多个)缺少ows_IDows_Titleows_Source_x0020_Message_x0020_File_属性。

Linq使用延迟执行,因此在您请求项目之前,它不会尝试构建序列。当您调用Any()或First()时,它只需要序列中的第一项就可以工作,这告诉我kobra.Descendants中的第一个项确实具有所有必需的节点。

但是,第一个之后的其中一个项可能至少缺少其中一个属性,因此您最终会要求NULL属性的Value

内部

select new Module 
{
    // properties...
}

在访问XML文档中可能不存在的元素的.Value时,可能会遇到NullReferenceException。集合中的第一个对象可能很好,因此使用Any()First()时会得到结果。后续项目可能缺少您尝试使用的元素/属性。

请尝试将其作为替换,而不是直接使用.Value

id = (string)s.Attribute("whatever") // etc.

您的一行(如s.Attribute("ows_Source_x0020_Message_x0020_File_"))将为其中一条记录返回null,因此s.Attribute("ows_Source_x0020_Message_x0020_File_").Value将导致null引用异常。