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

时间:2011-06-29 15:32:45

标签: c# .net linq

我有这个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()返回truekobraNodeList.First()返回完全有效且正确的带有所需数据的模块结构。

XML文件有效,如果我用这个替换linq查询:

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

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

3 个答案:

答案 0 :(得分:3)

看起来kobra.Descendants中有一个(或多个)ows_IDows_Titleows_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会导致空引用异常。