【问题标题】:Getting null reference Exception while parsing XML through LINQ通过 LINQ 解析 XML 时获取空引用异常
【发布时间】:2011-12-09 07:20:22
【问题描述】:

大家好,我正在解析以下类型的 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)
                        });

堆栈跟踪

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 行是黄色突出显示的行

【问题讨论】:

  • 你能发布异常堆栈跟踪吗?或者至少指出异常是否源自GetParamsList
  • 您为什么使用 xml 的屏幕截图?这让我们真的很难尝试重现以帮助您...
  • 添加了出现异常的快照
  • 您现在可以复制 XML
  • 你能发布确切的堆栈跟踪吗?

标签: c# .net xml linq nullreferenceexception


【解决方案1】:

错误:

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

通过这些更改,它可以工作。这里也不需要XmlDocumentXElement.Load() 会更好。我个人会改用XmlSerializer,但是……嗯。

【讨论】:

  • 非常感谢 Marc 的详细描述
【解决方案2】:

null ref 的基本原因:

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

flist 已经是&lt;Functions&gt; 元素。

【讨论】:

  • 这也是一个正确的答案,但我只能标记一个正确的,无论如何非常感谢。
【解决方案3】:

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

更明确地说,尝试改变

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

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

【讨论】:

  • 那么同样的问题,实际上使用 Outer fList 是 gettign 相同的值,包括添加的这一行 ,它存在于 XML 中跨度>
  • 我在调试模式下检查了 fList 是 gettign 完整的 XML 内容作为值
  • 我想说的是:根本不要使用 InnerXml (OuterXml) 或 Parse()。只需从文件名加载 XDocument。
  • XmlDocument xmlDoc = new XmlDocument(); xmlDoc.Load(pXMLPath); XElement fList = XElement.Parse(xmlDoc.InnerXml);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-06-28
  • 1970-01-01
  • 1970-01-01
  • 2012-02-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多