<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")) {
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")) {
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( ); } 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( ); } } 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( ); } } private static void Main(string[] args) { var settings = new XmlReaderSettings { IgnoreWhitespace = true }; using (var xr = XmlReader.Create("XMLFile1.xml", settings)) { ReadData(xr); } Console.ReadKey(); } } }
lesscode
source share