XmlReader ReadStartElement throws an XmlException

I am writing a file reader using XmlReader in a Silverlight project. However, I am getting some errors (especially around the XmlReader.ReadStartElement method), and this makes me believe that I misunderstood how to use it somewhere along the way.

Basically, here is an example of the Xml format that I use:

<?xml version="1.0" encoding="utf-8" standalone="no"?> <root> <EmptyElement /> <NonEmptyElement Name="NonEmptyElement"> <SubElement Name="SubElement" /> </NonEmptyElement> </root> 

And here is an example of code that uses the same way I use it:

 public void ReadData(XmlReader reader) { // Move to root element reader.ReadStartElement("root"); // Move to the empty element reader.ReadStartElement("EmptyElement"); // Read any children while(reader.ReadToNextSibling("SubEmptyElement")) { // ... } // Read the end of the empty element reader.ReadEndElement(); // Move to the non empty element reader.ReadStartElement("NonEmptyElement"); // NOTE: This is where I get the error. // ... } 

So, in essence, I'm just trying to read every element and any children it contains. The error I get at the highlighted point is as follows:

Error description

[Xml_InvalidNodeType] Arguments: none, 10.8 Debugging resource strings is not available. Often, the key and arguments provide enough information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=4.0.51204.0&File=System.Xml.dll&Key=Xml_InvalidNodeType

Error stack trace

in System.Xml.XmlReader.ReadStartElement (row name) at ----------------

Any advice or guidance on this subject would be greatly appreciated.

EDIT Because this reader should be fairly general, it can be assumed that the Xml may contain elements that are children of the EmptyElement. Thus, an attempt to read any SubEmptyElements elements must be valid.

+6
c # silverlight xmlreader
source share
1 answer

<SubElement/> not a brother of <EmptyElement> , so <NonEmptyElement> will be completely skipped, and your call to ReadEndElement() will read the final element </root> . When you try to read "NonEmptyElement" later, there are no elements left and you will get an XmlException: {"'None' is an invalid XmlNodeType. Line 8, position 1." }

Note that since <EmptyElement/> empty when you ReadStartElement ("EmptyElement"), you will read the entire element and you will not need to use ReadEndElement ().

I also recommend that you configure your readerโ€™s options on IgnoreWhitespace (if youโ€™re not already doing this) to avoid any complications when reading (minor) text nodes when you donโ€™t expect them.

Try moving Read of NonEmptyElement up:

 public static void ReadData(XmlReader reader) { reader.ReadStartElement("root"); reader.ReadStartElement("EmptyElement"); reader.ReadStartElement("NonEmptyElement"); while (reader.ReadToNextSibling("SubEmptyElement")) { // ... } reader.ReadEndElement(/* NonEmptyElement */); reader.ReadEndElement(/* root */); // ... } 

If you just want to skip something in <EmptyElement> , regardless of whether it is really empty, use ReadToFollowing :

 public static void ReadData(XmlReader reader) { reader.ReadStartElement("root"); reader.ReadToFollowing("NonEmptyElement"); Console.WriteLine(reader.GetAttribute("Name")); reader.ReadStartElement("NonEmptyElement"); Console.WriteLine(reader.GetAttribute("Name")); while (reader.ReadToNextSibling("SubEmptyElement")) { // ... } reader.ReadEndElement(/* NonEmptyElement */); reader.ReadEndElement(/* root */); // ... } 

Update: here is a more complete example with a clearer data model. Perhaps this is closer to what you are asking.

XMLFile1.xml:

 <?xml version="1.0" encoding="utf-8" standalone="no"?> <root> <Person Type="Homeless"/> <Person Type="Developer"> <Home Type="Apartment" /> </Person> <Person Type="Banker"> <Home Type="Apartment"/> <Home Type="Detached"/> <Home Type="Mansion"> <PoolHouse/> </Home> </Person> </root> 

Program.cs:

 using System; using System.Xml; namespace ConsoleApplication6 { internal class Program { public static void ReadData(XmlReader reader) { reader.ReadStartElement("root"); while (reader.IsStartElement("Person")) { ReadPerson(reader); } reader.ReadEndElement( /* root */); } public static void ReadPerson(XmlReader reader) { Console.WriteLine(reader.GetAttribute("Type")); bool isEmpty = reader.IsEmptyElement; reader.ReadStartElement("Person"); while (reader.IsStartElement("Home")) { ReadHome(reader); } if (!isEmpty) { reader.ReadEndElement( /* Person */); } } public static void ReadHome(XmlReader reader) { Console.WriteLine("\t" + reader.GetAttribute("Type")); bool isEmpty = reader.IsEmptyElement; reader.ReadStartElement("Home"); if (!isEmpty) { reader.Skip(); reader.ReadEndElement( /* Home */); } } private static void Main(string[] args) { var settings = new XmlReaderSettings { IgnoreWhitespace = true }; using (var xr = XmlReader.Create("XMLFile1.xml", settings)) { ReadData(xr); } Console.ReadKey(); } } } 
+5
source share

All Articles