I have written an Xml file using XmlWriter. Here is the code:
public void WriteXml(XmlWriter writer)
{
writer.WriteStartElement("element1");
writer.WriteAttributeString("attrs1", Attrs1);
writer.WriteAttributeString("attrs2", Attrs2);
if (!string.IsNullOrWhiteSpace("element2"))
{
writer.WriteStartElement("element2");
writer.WriteCData(Element2);
writer.WriteEndElement();
}
if (!string.IsNullOrWhiteSpace("element3"))
{
writer.WriteStartElement("element3");
writer.WriteCData(Element3);
writer.WriteEndElement();
}
Element4.WriteXml(writer);
Element5.WriteXml(writer);
writer.WriteEndElement();
}
As you can see, element4 calls a method named "WriteXml()". Here is that method:
public void WriteXml(XmlWriter writer)
{
if (m_PropertyValueList.Count > 0)
{
writer.WriteStartElement("element4");
foreach (var p in m_PropertyValueList)
{
if (p.CurrentValue != null)
{
writer.WriteStartElement("property");
writer.WriteAttributeString("name", p.PropertyName);
writer.WriteAttributeString("value", p.CurrentValue.ToString());
writer.WriteEndElement();
}
}
writer.WriteEndElement();
}
}
Notice that it checks for p.CurrentValue != null. If it is null then this element should be written as an empty element. In this case, p.CurrentValue is null so I do want an empty element. You will see in the Xml output below that is writing this element as . To me it looks like it is properly writing an empty element, PLEASE CORRECT ME IF I'M WRONG HERE.
The Xml file output looks like this:
<?xml version="1.0" encoding="UTF-8"?>
-<element>
-<element 1 attrs1="Some Info" attrs2="More Info">
-<element2>
+<![CDATA[]]>
</element2>
-<element3>
-<![CDATA[ ]]>
</element3>
<element4/>
</element1>
</element>
Then I create a method for reading the Xml file back in. This is where it breaks. It does just fine reading element, element1, element2 and element3. However, when it gets to element4, I start having issues. I will explain below.
Here is the XmlReader method:
public void ReadXml(XmlReader reader)
{
if (reader.IsStartElement("element1"))
{
//
// Get the values of all the <element1> attributes
//
Attrs1= reader.GetAttribute("attrs1");
Attrs2 = reader.GetAttribute("attrs2");
//
// Read past <element1>
//
reader.Read();
while (true)
{
if (reader.IsStartElement("element2"))
{
Description = reader.ReadElementContentAsString();
}
else if (reader.IsStartElement("element3"))
{
Source = reader.ReadElementContentAsString();
}
else if (reader.IsStartElement("element4")) && (!reader.IsEmptyElement))
{
Element4.ReadXml(reader);
}
else if ((reader.IsStartElement("element5")) && (!reader.IsEmptyElement))
{
Element5.ReadXml(reader);
}
else
{
reader.MoveToContent();
reader.ReadEndElement();
break;
}
}
}
else
{
throw new XmlException("Expected <element1> element was not present");
}
}
Notice that if element4 IsStartElement and if it's not an empty element it will call Element4.ReadXml(). Here is that method:
public void ReadXml(XmlReader reader)
{
if ((reader.IsStartElement("element4")) && (!reader.IsEmptyElement))
{
reader.Read();
while (reader.IsStartElement("property"))
{
string propertyName = reader.GetAttribute("name");
string propertyValue = reader.GetAttribute("value");
SetValue(propertyName, propertyValue);
reader.Read();
}
//
// Read </element4>
//
reader.MoveToContent();
reader.ReadEndElement();
}
}
But since element4 IS empty this method never gets called. So it will continue to the else{} statement and break when it gets to reader.ReadEndElement(); There error message I get is:
"Message: TestMethod myTestMethodName threw exception: System.Xml.XmlException 'Element' is an invalid XmlNodeType. Line 8, position 6."
So my questions are:
Where I read my elements from my xml file I needed to add another else if condition to handle if the element is start element and if the element IS empty. I was only checking if it wasn't empty. So it didn't know how to handle it being empty. Then when those conditions were met I simply had to do reader.Read() to tell the app to read the element as is <element4/>
.
Here is what it looks like:
else if (reader.IsStartElement("element4")) && (reader.IsEmptyElement))
{
reader.Read();
}