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()
返回true
,kobraNodeList.First()
返回一个具有所需数据的完全有效且正确的Module结构。
XML文件是有效的,如果我用以下内容替换linq查询:
var kobraNodeList = from s in kobra.Descendants(ns + "row")
select s;
我得到了一个有效的XElement列表,我可以Count()
ok。有人能解释我怎么了吗?顺便说一句,我用的是.NET 3.5。
看起来kobra.Descendants
中的一个(或多个)缺少ows_ID
、ows_Title
或ows_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引用异常。