2011-06-29 58 views
0

我有这个XML文件,我解析到它的元素并创建一个自定义对象模块的列表。XML linq查询列出第一个元素,但不是全部

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()返回一个完美有效和正确的模块结构与所需的数据。

的XML文件是有效的,如果我更换与此LINQ查询:

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

我得到的XElement的有效列表,我可以Count()确定。 有人可以解释我有什么问题吗?顺便说一句,我使用.NET 3.5。

回答

3

看起来像kobra.Descendants中的一个(或多个)有ows_ID,ows_Titleows_Source_x0020_Message_x0020_File_属性缺失。

Linq使用deferred execution,所以它不会尝试构建序列,直到您要求项目。当您调用Any()或First()时,它只需要序列中的第一个项目工作,这告诉我kobra.Descendants中的第一个项目确实具有所有必需的节点。

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

2

select new Module 
{ 
    // properties... 
} 

你可能会运行到一个NullReferenceException因为你可能不会在XML文档中存在的元素访问.Value。您收集的第一个对象可能没有问题,因此您在使用Any()First()时会得出结果。后续项目可能会丢失您尝试使用的元素/属性。

试试用这个代替直接使用.Value

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

Holy sh **你是对的,我100%肯定XML文件是完整的所有属性,不可能是原因。谢谢! – Antoine

0

一个你的线条,如s.Attribute("ows_Source_x0020_Message_x0020_File_")将用于的记录,以便s.Attribute("ows_Source_x0020_Message_x0020_File_").Value之一返回null将导致空引用异常。