如何使用LINQ解析可选或空的XML元素和属性?

我有以下类型的XML:

在此处输入图像描述

通过这个XML,我希望填充以下objectList。

List objFunctionsList = new List(); 

其中Function类如下,

 public class Function { public String Name { get ; set; } public Parameter ReturnType { get; set; } public List Parameters { get; set; } public String Library { get; set; } public String Signature { get; set; } public String Description { get; set; } public String Code { get; set; } } 

而Parameter类如下,

 public class Parameter { [DefaultValue("")] public String Name { get; set; } [DefaultValue("")] public String DataType { get; set; } [DefaultValue("")] public String OccurenceType { get; set; } } 

您可以看到,在XML中,某些函数标记具有Parameters标记,而其他函数标记则没有。 我试过这个:

 public const string XPATH_NAME = "/Functions/Function/Name"; public const string XPATH_LIBRARY = "/Functions/Function/Library"; public const string XPATH_SIGNATURE = "/Functions/Function/Signature"; public const string XPATH_DESCRIPTION = "/Functions/Function/Description"; public const string XPATH_CODE = "/Functions/Function/Code"; List objFunctionsList = new List(); try { XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(pXMLPath); XmlNodeList nlName = xmlDoc.SelectNodes(Constants.XPATH_NAME); XmlNodeList nlLibrary = xmlDoc.SelectNodes(Constants.XPATH_LIBRARY); XmlNodeList nlSignature = xmlDoc.SelectNodes(Constants.XPATH_SIGNATURE); XmlNodeList nlDescription = xmlDoc.SelectNodes(Constants.XPATH_DESCRIPTION); XmlNodeList nlCode = xmlDoc.SelectNodes(Constants.XPATH_CODE); // Name, Signature, Library, element should be present in 'Function' node if (nlName.Count == nlLibrary.Count && nlName.Count == nlSignature.Count && nlName.Count == nlDescription.Count && nlName.Count == nlCode.Count) { for (int iCount = 0; iCount  0) { objReturnType.DataType = returnType; } objFunction.ReturnType = objReturnType; objFunction.Parameters = new List(); objFunction.Signature = signature; objFunction.Description = nlDescription[iCount].InnerText.Trim(); objFunction.Code = nlCode[iCount].InnerText.Trim(); objFunctionsList.Add(objFunction); } } } 

但这是基于XPath的代码,并且在我没有在函数标记中使用参数标记时使用。

正如@NitinRastogi在他的回答中 提到的那篇文章所指出的那样,你可以使用LINQ的一些方便属性来轻松解决null或可选值:

  1. 如果没有找到结果或者将空集合作为输入传递,则返回集合的方法(如Elements()将返回空集合(非null ):

    如果将空集合传递给Attributes扩展方法,它也会返回一个空集合。

  2. 某些返回单个值的LINQ方法First()First()也会返回一个默认值的变量,如果没有找到对象,则返回null ,而不是引发exception。 在First()的情况下,它的变体是FirstOrDefault()

因此,在您的情况下,由于Parameters对于Function对象是可选的,您可以选择使用等于null Parameters或空列表初始化它们。

案例1:使用null初始化

如果要将它们初始化为null ,则可以执行以下操作:

 var doc = // XDocument.Load() or XDocument.Parse() ... var functions = from f in doc.Root.Elements() select new { // ... Parameters = f.Elements("parameters").Elements().Count() == 0 ? null : ( from p in f.Elements("parameters").Elements() select new { DataType = p.Attribute("type"), Name = p.Attribute("name"), Occurence = p.Attribute("occurence") }) .ToList() // ... }; 

案例2:使用列表初始化(0个或更多元素)

但这导致了很多丑陋的null检查代码。 更简单的方法是使用包含0个或更多元素的列表进行初始化。 如果没有参数,这些LINQ和XElement集合方法都将返回一个空集合,因此函数的Parameters属性将只是一个空列表而不是null:

 var doc = // XDocument.Load() or XDocument.Parse() ... var functions = from f in doc.Root.Elements() select new { // ... Parameters = ( from p in f.Elements("parameters").Elements() select new { DataType = p.Attribute("type"), Name = p.Attribute("name"), Occurence = p.Attribute("occurence") }) .ToList() // ... };