在通过LINQ解析XML时获取空引用异常

时间:2011-12-09 07:20:23

标签: c# .net xml linq nullreferenceexception

嗨大家我正在使用以下类型的XML进行解析。

<?xml version="1.0" encoding="utf-8" ?>
<Functions>

<Function>
<Name>local:FunctionName</Name>
<Library>UserDefined</Library>
<Signature type="xs:decimal+">local:FunctionName(#?VALUE#,arg1,arg2,arg3) as xs:decimal+</Signature>
<Description>Some comments</Description>
<Code><![CDATA[some code]]></Code>
</Function>

<Function>
<Name>local:NewFunction</Name>
<Library>UserDefined</Library>
<Signature type="xs:decimal+">local:NewFunction(num1 as xs:string+,num2 as xs:string+,num3 as xs:string+) as xs:decimal+</Signature>
<Parameters>
     <Parameter type="xs:string" occurence="+" name="num1">num1 as xs:string+</Parameter>
     <Parameter type="xs:string" occurence="+" name="num2">num2 as xs:string+</Parameter>
     <Parameter type="xs:string" occurence="+" name="num3">num3 as xs:string+</Parameter>
</Parameters>
<Description>Some comments</Description>
<Code><![CDATA[some code]]></Code>
</Function>


</Functions>

在解析后我必须填充以下模型

 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;}
    }

   and the Parameter class is as follows

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

    [DefaultValue("")]
    public String DataType{get;set;}

    [DefaultValue("")]
    public String OccurenceType {get; set;}
}

我正在尝试的代码如下。我正在调用下面写的函数来填充列表。

public static List<Function> GetAllFunctions(String pXMLPath)
        {
            List<Function> objFunctionsList = new List<Function>(); 

            try
            {
                XmlDocument xmlDoc = new XmlDocument();
                xmlDoc.Load(pXMLPath);


                XElement fList = XElement.Parse(xmlDoc.InnerXml);

                // In following 10 lines I am getting Null-reference exception
                var Functions = fList
                    .Element("Functions")
                    .Elements("Function")
                    .Select(Function => new
                        {
                            Name = (string)Function.Element("Name"),
                            Library = (string)Function.Element("Library"),
                            Signature = (string)Function.Element("Signature"),
                            ReturnType = (string)Function.Attribute("type"),
                            Description = (string)Function.Element("Description"),
                            Code = (string)Function.Element("Code"),
                            Parameters =  GetParamsList(Function)
                        });

                foreach (var f in Functions)
                {
                    Function objFunction = new Function();
                    objFunction.Name = f.Name;
                    objFunction.Library = f.Library;
                    objFunction.Description = f.Description;
                    objFunction.Code = f.Code;
                    objFunction.Signature = f.Signature;
                    objFunction.State = 0;//Unmodified (Save not required)

                    #region Populating Return Type

                    string returnType = f.ReturnType;
                    string signature = f.Signature;

                    Parameter objReturnType = new Parameter();
                    if (String.IsNullOrEmpty(returnType) || returnType == Constants.XSNOPARAM)
                    {
                        objReturnType.Name = string.Empty;
                        objReturnType.OccurenceType = string.Empty;
                        objReturnType.DataType = Constants.XSNOPARAM;
                    }
                    else
                    {

                        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;
                        }

                    } 
                    #endregion

                    objFunction.ReturnType = objReturnType;

                    objFunction.Parameters = new List<Parameter>();
                    foreach (var param in f.Parameters.ToList())
                    {
                        Parameter objParam = new Parameter();

                        objParam.Name = param.Name;
                        objParam.DataType = param.DataType;
                        objParam.OccurenceType = param.OccurenceType;

                        objFunction.Parameters.Add(objParam);
                    }

                    objFunctionsList.Add(objFunction);

                }

            }
            catch (Exception ex)
            {

            }
            return objFunctionsList;
        }

private static List<Parameter> GetParamsList(XElement pParametersElement)
        {
            if (pParametersElement != null)
            {
                   var Parameters = pParametersElement
                    .Elements("Parameter")
                   .Select(Parameter => new
                   {
                       Name = (string)Parameter.Attribute("name"),
                       Occurence = (string)Parameter.Attribute("occurence"),
                       Type = (string)Parameter.Attribute("type")
                   });

                List<Parameter> objParamsList = new List<Parameter>();

                foreach (var param in Parameters)
                {
                    Parameter objParam = new Parameter();
                    objParam.Name = param.Name;
                    objParam.OccurenceType = param.Occurence;
                    objParam.DataType = param.Type;

                    objParamsList.Add(objParam);
                }
                return objParamsList;
            }
            else
                return null;
        }

主要在以下代码中我得到了例外

 var Functions = fList
                    .Element("Functions")
                    .Elements("Function")
                    .Select(Function => new
                        {
                            Name = (string)Function.Element("Name"),
                            Library = (string)Function.Element("Library"),
                            Signature = (string)Function.Element("Signature"),
                            ReturnType = (string)Function.Attribute("type"),
                            Description = (string)Function.Element("Description"),
                            Code = (string)Function.Element("Code"),
                            Parameters =  GetParamsList(Function)
                        });

enter image description here

堆栈跟踪

Type : System.NullReferenceException, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
Message : Object reference not set to an instance of an object.
Source : MyApp.XEG.Utility
Help link : 
Data : System.Collections.ListDictionaryInternal
TargetSite : System.Collections.Generic.List`1[MyApp.XEG.Model.Function] GetAllFunctions(System.String)
Stack Trace :    at MyApp.XEG.Utility.CFLFile.GetAllFunctions(String pXMLPath) in C:\MyApp\XEG.Utility\CFLFile.cs:line 189

此处,第189行是黄色突出显示的行

3 个答案:

答案 0 :(得分:2)

错误:

  • 恶化异常!
  • 您需要var Functions = fList.Elements("Function").等 - 首先没有“功能”(在顶部)
  • 您需要Parameters = GetParamsList(Function.Element("Parameters"))(正好在其下方)
  • 您需要对参数进行空值检查:if (f.Parameters != null) foreach(var param in f.Parameters) {...}(靠近GetAllFunctions的底部)

有了这些变化,它就有效了。此处也不需要XmlDocument; XElement.Load()会更好。就个人而言,我会使用XmlSerializer代替,但是...... meh。

答案 1 :(得分:2)

null ref的基本原因:

 var Functions = fList
 //  .Element("Functions")
   .Elements("Function")
   ....

flist已经是<Functions>元素。

答案 2 :(得分:0)

尝试在解析中使用xmlDoc.OuterXml。您只是解析文档元素中的内容,然后尝试在第一个.Element()调用中引用文档元素。

更明确地说,尝试更改

XElement fList = XElement.Parse(xmlDoc.InnerXml);

XElement fList = XElement.Parse(xmlDoc.OuterXml);