如何使用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的代码,并且在我没有在函数标记中使用参数标记时使用。
检查一下,看看这是否有帮助 – http://blogs.msdn.com/b/ericwhite/archive/2009/05/14/working-with-optional-elements-and-attributes-in-linq-to-xml- queries.aspx
正如@NitinRastogi在他的回答中 提到的那篇文章所指出的那样,你可以使用LINQ的一些方便属性来轻松解决null
或可选值:
-
如果没有找到结果或者将空集合作为输入传递,则返回集合的方法(如
Elements()
将返回空集合(非null
):如果将空集合传递给
Attributes
扩展方法,它也会返回一个空集合。 -
某些返回单个值的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() // ... };