Abhi
Abhi

Reputation: 5561

Getting null reference Exception while parsing XML through LINQ

Hi Guys I am having following type of XML to parse.

<?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>

and after Parsing I have to populate following Models

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

where Function class is as follows

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

The Code that i am trying is below. I am calling function written below to get list populated.

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

Mainly in following code i m getting 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)
                        });

enter image description here

Stack Trace

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

here the line 189 is the highlighted line in yellow

Upvotes: 1

Views: 1599

Answers (3)

Henk Holterman
Henk Holterman

Reputation: 273244

The basic reason for the null ref:

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

flist already is the <Functions> element.

Upvotes: 2

Marc Gravell
Marc Gravell

Reputation: 1062770

Errors:

  • swalling the exception!
  • you need var Functions = fList.Elements("Function"). etc - no "Functions" first (at the top)
  • you need Parameters = GetParamsList(Function.Element("Parameters")) (just below that)
  • you need to null-check the parameters: if (f.Parameters != null) foreach(var param in f.Parameters) {...} (near the bottom of GetAllFunctions)

with those changes, it works. There is also no need for XmlDocument in here; XElement.Load() would be preferable. Personally I'd use XmlSerializer instead, but ... meh.

Upvotes: 1

Daniel Renshaw
Daniel Renshaw

Reputation: 34177

Try using xmlDoc.OuterXml in your parse. You're only parsing the content inside the document element but then trying to reference the document element in the first .Element() call.

More explicitly, try changing

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

to

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

Upvotes: 0

Related Questions