Da Bazz Da Bazz - 24 days ago 3
C# Question

Linq XML NullReference Exception on reading list of elements

I'm trying to read a list of Text nodes from my Xml file. When I try to read the children nodes of 1 of the listed text elements I get the NullReference exception, even though the XDocument nodes are seemingly filled.
The NullReference exception is thrown on the line

foreach (XElement textElement in textElements)
this means that the list textElements has a Count > 1 so it shouldn't be null. That's as far as the debugger is willing to go.

Am I reading the Xml in the wrong way, or am I not allowed to / shouldn't build the XElement lists the way I am now?

This is my Xml file

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE Book SYSTEM "Book.dtd"[]>
<album version="0.2" settingsVersion="1">
<size />
<cover />
<inner>
<page>
<pagenumber>1</pagenumber>
<image>1.jpg</image>
<text>
<value>Test </value>
<font>arial</font>
<size>18pt</size>
<style>normal</style>
<weight>normal</weight>
<color>#77DD44</color>
<rotation>0</rotation>
<alignment>start</alignment>
<position>
<x>50</x>
<y>50</y>
</position>
</text>
<text>
<value>Test 2 </value>
<font>arial</font>
<size>18pt</size>
<style>normal</style>
<weight>normal</weight>
<color>#77DD44</color>
<rotation>0</rotation>
<alignment>start</alignment>
<position>
<x>50</x>
<y>50</y>
</position>
</text>
</page>
</inner>
</album>


Element
inner
can hold multiple
page
elements and
page
can hold multiple
text
elements.

I read the Xml in the following method.


List<XElement> pageElements = doc.Root.Element("inner").Elements("page").ToList();
foreach (XElement pageElement in pageElements)
{
string pageNumberString = pageElement.Element("pagenumber").Value;
int pageNumberValue = Convert.ToInt32(pageNumberString);
string fileNameValue = pageElement.Element("image").Value;
// Verify if the currently looped page is the same as the one selected by the user.
if (pageNumberValue == pageNumber)
{
// Get all text nodes from the found page.
List<XElement> textElements = pageElement.Elements("text").ToList();
// If no text nodes found return the page with an empty TextInfo array.
if (textElements.Count == 0)
{
PageInfo pageInfoNoText = new PageInfo { PageNumber = pageNumberValue, FileName = fileNameValue, Text = new TextInfo[0] };
Logger.log("PageInfo found for collection {0}. Info {1}", collectionId, pageInfoNoText);
return pageInfoNoText;
}
// If text nodes are found build a list of TextInfo objects and build a new PageInfo object.
else
{
// All text elements in the XML under the found page.
List<TextInfo> textInfoList = new List<TextInfo>();
TextInfo[] textArray = new TextInfo[0];

#region Load all required text data from the XML file and build the textList.
foreach (XElement textElement in textElements)
{
string textValue = textElement.Element("value").Value;

string fontValue = textElement.Element("font").Value;

string fontSizeValue = textElement.Element("size").Value;

string styleValue = textElement.Element("style").Value;

string weightValue = textElement.Element("weight").Value;

string colorValue = textElement.Element("color").Value;

string rotationString = textElement.Element("rotation").Value;
int rotationValue = Convert.ToInt32(rotationString);

string alignmentValue = textElement.Element("alignment").Value;

string positionXString = textElement.Element("x").Value;
int positionXValue = Convert.ToInt32(positionXString);

string positionYString = textElement.Element("y").Value;
int positionYValue = Convert.ToInt32(positionYString);

// Build Info objects.
PositionInfo tempPositionInfo = new PositionInfo
{
X = positionXValue,
Y = positionYValue
};

TextInfo tempTextInfo = new TextInfo
{
Value = textValue,
Font = fontValue,
Size = fontSizeValue,
Style = styleValue,
Weight = weightValue,
Color = colorValue,
Rotation = rotationValue,
Alignment = alignmentValue,
Position = tempPositionInfo
};

textInfoList.Add(tempTextInfo);

}
textArray = textInfoList.ToArray();
#endregion

PageInfo pageInfo = new PageInfo
{
PageNumber = pageNumberValue,
FileName = fileNameValue,
Text = textArray
};
Logger.log("PageInfo found for collection {0}. Info: {1}", collectionId, pageInfo);
return pageInfo;

}
}
}


Any help / insight is appreciated!

Answer

your code is fine but there is a mistake when you get x and y values, you need to get x and y values of position element as below

string positionXString = (string)textElement.Element("position").Element("x").Value;
int positionXValue = Convert.ToInt32(positionXString);
string positionYString = (string)textElement.Element("position").Element("y").Value;
int positionYValue = Convert.ToInt32(positionYString);
Comments