Khalil Khalaf
Khalil Khalaf

Reputation: 9397

Xml reader error: Object reference not set to an instance of an object

I have large number of Xml files that contain double, int, DateTime, string, lists of objects .. etc. Mix of variable types similar to this:

<?xml version="1.0" encoding="utf-8"?>
<Verification xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <SerialNumber>1</SerialNumber>
  <Description>V1 From File</Description>
  <DateCreated>2016-04-22T09:27:54.193</DateCreated>
  <DesiredX>1.000000</DesiredX>
  <DesiredTargets count="3">
    <Sample X1="535.108154296875" X2="1058.36315917969" Y1="780.292175292969" Y2="1037.53625488281" A="-44.5051406645421" B="-2.8002082198978" C="-0.211281331705749" DifferenceA="-44.5051406645421" DifferenceB="-2.8002082198978" DifferenceC="-0.211281331705749" ReferenceNumber="0" TimeTaken="Tuesday, April 26, 2016 2:25:43 PM" />
    <Sample X1="529.666198730469" X2="533.695007324219" Y1="854.45654296875" Y2="514.573974609375" A="62.1131427426299" B="-4.93194374266585" C="-0.383094414887779" DifferenceA="62.1131427426299" DifferenceB="-4.93194374266585" DifferenceC="-0.383094414887779" ReferenceNumber="1" TimeTaken="Tuesday, April 26, 2016 2:25:43 PM" />
    <Sample X1="172.242752075195" X2="777.789245605469" Y1="334.160064697266" Y2="740.525268554688" A="9.54891420214495" B="91.256891073657" C="0.329283687878274" DifferenceA="9.54891420214495" DifferenceB="91.256891073657" DifferenceC="0.329283687878274" ReferenceNumber="2" TimeTaken="Tuesday, April 26, 2016 2:25:45 PM" />
  </DesiredTargets>
</Verification>

The list of objects is of type Sample, default constructor:

public Sample(Test targetTest, double newX1, double newX2, double newY1, double newY2, double newA, double newB, double newC, int sampleNum)

Class Verification which every Xml file will be loaded to an instance of it:

public class Verification
{
    public int SerialNumber { get; set; }
    public int ReferenceCount { get; set; }
    public string Description { get; set; }
    public DateTime DateCreated {get; set; }
    public double DesiredX { get; set; }
    public List<Sample> DesiredTargets { get; set; }
    // ..
    // other variables and functions
}

Mission: Load the Xml files

Purpose: I don't want to change every file's structure or tags to match certain code pattern like suggested here Load in a simple list of objects

Vision:

My code works using XmlSerializer when I had no List<Sample>. Now the file has a List<Sample> and the below code uses XDocument but pops an error:

Object reference not set to an instance of an object

using System.Xml;
using System.Xml.Schema;
using System.Xml.Serialization;
// ..

public void LoadFromFile(string path)
{
    // stuff
    // ..
    // to load list of Sample
    XDocument XmlReader = XDocument.Load(path);

    // pops the error here
    DesiredTargets =
        XmlReader.Root.Elements("DesiredTargets")
        .Select(h => new Sample(
            null,
            double.Parse(h.Element("X1").Value),
            double.Parse(h.Element("X2").Value),
            double.Parse(h.Element("Y1").Value),
            double.Parse(h.Element("Y2").Value),
            double.Parse(h.Element("A").Value),
            double.Parse(h.Element("B").Value),
            double.Parse(h.Element("C").Value),
            int.Parse(h.Element("ReferenceNumber").Value)
            ))
        .ToList();

        // I don't have the code using XDocument for other variables yet but it works when there is no List<> using XmlSerializer
}

Upvotes: 0

Views: 2487

Answers (1)

Charles Mager
Charles Mager

Reputation: 26223

Your code is trying to read child elements of DesiredTargets using h.Element("name").Value. If an element is not present, Element returns null and the call to the Value property will throw a NullReferenceException.

Not one of the 7 elements you're trying to read actually exist, so all of these will cause the problem you're seeing. They are not elements, they are attributes of the Sample element. As an aside, there are built-in explicit conversions in LINQ to XML that mean you don't have to parse the strings:

So, something like this would actually work:

doc.Descendants("DesiredTargets")
    .Elements("Sample")
    .Select(x => new Sample(
        null,
        (double)x.Attribute("X1"),
        (double)x.Attribute("X2"),
        (double)x.Attribute("Y1"),
        (double)x.Attribute("Y2"),
        (double)x.Attribute("A"),
        (double)x.Attribute("B"),
        (double)x.Attribute("C"),
        (int)x.Attribute("ReferenceNumber"))
    ).ToList();

That said, you'd be far better off using XmlSerializer than hand coding the serialisation yourself. List<T> shouldn't be a problem.

Upvotes: 1

Related Questions