Using XmlReader.Read() with ReadElementContentAs*()

Most samples of using an XmlReader use a Read in a while loop like this:

var value1 = 0;
var value2 = 0;
var value3 = 0;
while (reader.Read())
{
    if(reader.IsStartElement())
    {
        switch(reader.Name)
        {
            case "Element1":
                value1 = reader.ReadElementContentAsInt();
                break;
            case "Element2":
                value2 = reader.ReadElementContentAsInt();
                break;
             case "Element3":
                value3++;
                break;
         }
    }
}

However, this pattern may fail if elements are not separated by whitespace. The culprits are the ReadElementContentAs* methods. Without separating whitespace they leave the reader at the start of the next element. The Read at the top of the loop moves it past this next start element and it will be skipped completely.

This is particularly nasty because it works well with nicely formatted XML, which you’ll probably use while testing, because it has whitespace between elements. However, dense XML generated by a feeding system will trip it up.

Instead you can use something like this:

var value1 = 0;
var value2 = 0;
var value3 = 0;
while (!reader.EOF)
{
    if(reader.IsStartElement())
    {
        switch(reader.Name)
        {
            case "Element1":
                value1 = reader.ReadElementContentAsInt();
                continue;
            case "Element2":
                value2 = reader.ReadElementContentAsInt();
                continue;
            case "Element3":
                value3++;
                break;
        }
    }
    reader.Read();
}

The Read at the top of the loop is replaced by an EOF check and moved to the bottom. This allows skipping it with the continue keyword after using a ReadElementContentAs* method or anything else that leaves the reader at the start of the next element. Anything else is followed by a break to move the reader forward.

Please note the use of continue instead of break is rather subtle so a comment is probably in order.

BTW, if you want to test XML documents without having to edit terse XML files load pretty formatted XML in an XDocument and then open an XmlReader from it. Apparently this reads the XML without the whitespace nodes.

Advertisements