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

C# 如何解析可选或空XML元素&;LINQ的属性?,c#,.net,xml,linq,xml-parsing,C#,.net,Xml,Linq,Xml Parsing,我有以下类型的XML: 我希望通过这个XML填充以下objectList List<Function> objFunctionsList = new List<Function>(); 您可以看到,在XML中,一些函数标记有Parameters标记,而另一些没有。我试过这个: public const string XPATH_NAME = "/Functions/Function/Name"; public const string XPATH_LIBRARY =

我有以下类型的XML:

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

List<Function> objFunctionsList = new List<Function>();
您可以看到,在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);
        }
    }
}
public const string XPATH_NAME=“/Functions/Function/NAME”;
公共常量字符串XPATH_LIBRARY=“/Functions/Function/LIBRARY”;
public const字符串XPATH_SIGNATURE=“/Functions/Function/SIGNATURE”;
公共常量字符串XPATH_DESCRIPTION=“/Functions/Function/DESCRIPTION”;
公共常量字符串XPATH_CODE=“/Functions/Function/CODE”;
List objFunctionsList=新列表();
尝试
{
XmlDocument xmlDoc=新的XmlDocument();
加载(pXMLPath);
XmlNodeList nlName=xmlDoc.SelectNodes(Constants.XPATH\u NAME);
XmlNodeList nlLibrary=xmlDoc.SelectNodes(Constants.XPATH\u LIBRARY);
XmlNodeList nlSignature=xmlDoc.SelectNodes(Constants.XPATH\u签名);
XmlNodeList nlDescription=xmlDoc.SelectNodes(Constants.XPATH\u DESCRIPTION);
XmlNodeList nlCode=xmlDoc.SelectNodes(Constants.XPATH\u代码);
//名称、签名、库、元素应出现在“功能”节点中
如果(nlName.Count==nlLibrary.Count
&&nlName.Count==nlSignature.Count
&&nlName.Count==nlDescription.Count
&&nlName.Count==nlCode.Count)
{
对于(int-iCount=0;iCount0)
{
objReturnType.DataType=returnType;
}
objFunction.ReturnType=objReturnType;
objFunction.Parameters=新列表();
objFunction.Signature=签名;
objFunction.Description=nlDescription[iCount].InnerText.Trim();
objFunction.Code=nlCode[iCount].InnerText.Trim();
objFunctionsList.Add(objFunction);
}
}
}

但这是基于XPath的代码,在我之前没有在函数标记中使用Parameters标记时使用过。

检查这一点,看看这是否有帮助-

如中所述,您可以使用LINQ的一些方便的属性来轻松处理
null
或可选值:

  • 返回集合(例如)的方法将返回空 如果未找到任何结果或它们作为空集合传递,则返回集合(非
    null
    ) 输入:

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

  • 一些返回单个值的LINQ方法,例如 如果找不到对象,将返回默认值的变量,例如
    null
    , 而不是提出一个例外。对于
    First()
    ,其变体为

  • 因此,在您的情况下,由于
    参数
    对于
    函数
    对象是可选的,因此您可以选择使用
    参数
    等于
    或空列表来初始化它们

    案例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()
            // ...
        };
    

    我已经更新了我尝试的代码如果函数没有参数,这是否意味着它的
    参数
    成员应该是
    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()
            // ...
        };
    
    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()
            // ...
        };