Reputation: 9397
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:
Any variables that doesn't exist in the Xml, should be set as null
(happens by default?) Here I know that the parameter targetTest
is missing, which the Sample
constructor needs, but what if I don't know what is missing? Also I know that ReferenceCount
for class Verification
is not in the xml.. etc.
A code that matches the files and not edit all files to match a code
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
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