我有这个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转换为模块列表时,事情变得奇怪,我在System.NullReferenceException
行得到AddRange
:
this.moduleList = new List<Module>;
this.moduleList.AddRange(kobraNodeList);
尝试调试时,我注意到虽然kobraNodeList.Count()
也返回System.NullReferenceException
,但kobraNodeList.Any()
返回true
,kobraNodeList.First()
返回完全有效且正确的带有所需数据的模块结构。
XML文件有效,如果我用这个替换linq查询:
var kobraNodeList = from s in kobra.Descendants(ns + "row")
select s;
我得到一个有效的XElement列表,我可以Count()
好。
有人能解释我有什么不对吗?顺便说一句,我使用的是.NET 3.5。
答案 0 :(得分:3)
看起来kobra.Descendants
中有一个(或多个)ows_ID
,ows_Title
或ows_Source_x0020_Message_x0020_File_
属性丢失。
Linq使用deferred execution,因此在您要求提供项目之前不会尝试构建序列。当你调用Any()或First()时,它只需要序列中的第一项工作,这告诉我kobra.Descendants
中的第一项确实拥有所有必需的节点。
但是,第一个项目之后的其中一个项目可能至少缺少其中一个属性 - 因此您最终要求Value
属性NULL
。
答案 1 :(得分:2)
内部
select new Module
{
// properties...
}
当您在XML文档中可能不存在的元素上访问.Value
时,您可能会遇到NullReferenceException。您在集合中的第一个对象可能很好,因此在使用Any()
或First()
时会产生结果。后续项目可能缺少您尝试使用的元素/属性。
尝试将此作为替代品,而不是直接使用.Value
。
id = (string)s.Attribute("whatever") // etc.
答案 2 :(得分:0)
您的其中一行(例如s.Attribute("ows_Source_x0020_Message_x0020_File_")
)将为其中一条记录返回null,因此s.Attribute("ows_Source_x0020_Message_x0020_File_").Value
会导致空引用异常。