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

时间:2011-12-09 05:45:12

标签: c# .net xml linq xml-parsing

我有以下类型的XML:

enter image description here

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

List<Function> objFunctionsList = new List<Function>();

其中Function类如下,

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

,参数类如下,

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<Function> objFunctionsList = new List<Function>();

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 < nlName.Count; iCount++)
        {
            Function objFunction = new Function();
            objFunction.Name = nlName[iCount].InnerText.Trim();
            objFunction.Library = nlLibrary[iCount].InnerText.Trim();
            string signature = nlSignature[iCount].InnerText;

            Parameter objReturnType = new Parameter();
            string returnType = (nlSignature[iCount].Attributes[Constants.ATRR_TYPE] == null
                ? Constants.XSNOPARAM
                : nlSignature[iCount].Attributes[Constants.ATRR_TYPE].Value);

            if (returnType.EndsWith(Constants.ASTERIK))
            {
                objReturnType.DataType = returnType.Substring(0, returnType.Length - 1);
                objReturnType.OccurenceType = Constants.OCCURENCES_ASTERISK;
            }
            else if (returnType.EndsWith(Constants.PLUS))
            {
                objReturnType.DataType = returnType.Substring(0, returnType.Length - 1);
                objReturnType.OccurenceType = Constants.OCCURENCES_PLUS;
            }
            else if (returnType.EndsWith(Constants.QUESTION_MARK))
            {
                objReturnType.DataType = returnType.Substring(0, returnType.Length - 1);
                objReturnType.OccurenceType = Constants.OCCURENCES_QUESTION;
            }
            else if (returnType.Length > 0)
            {
                objReturnType.DataType = returnType;
            }

            objFunction.ReturnType = objReturnType;

            objFunction.Parameters = new List<Parameter>();

            objFunction.Signature = signature;
            objFunction.Description = nlDescription[iCount].InnerText.Trim();
            objFunction.Code = nlCode[iCount].InnerText.Trim();

            objFunctionsList.Add(objFunction);
        }
    }
}

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

2 个答案:

答案 0 :(得分:2)

答案 1 :(得分:0)

the article that @NitinRastogi mentions中的his answer指出,您可以使用LINQ的一些方便属性,以便轻松解决null或可选值:

  1. 返回集合的方法(例如Elements())将返回空 集合(不是null)如果没有找到结果或者他们将空集合作为 输入:

      

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

  2. 一些返回单个值的LINQ方法,如First(),也有 如果没有找到对象,将返回默认值的变体,例如null, 而不是提出异常。在First()的情况下,其变体是 FirstOrDefault()

  3. 因此,在您的情况下,由于Parameters对象的Function是可选的,您可以选择使用等于Parameters的{​​{1}}或空列表对其进行初始化。

    案例1:使用null

    初始化

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

    null

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

    但是这导致了许多丑陋的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() // ... }; 检查代码。一种更简单的方法是使用包含0个或更多元素的列表进行初始化。如果没有参数,这些LINQ和null集合方法都将返回一个空集合,因此函数上的XElement属性只是一个空列表而不是null:

    Parameters