Reading XML

I have been playing with reading XML from a file for several days now, trying out the various methods in XMLReader and have found some surprising things. It is never clear where each method leaves the Reader pointing so you have to be very careful about using a particular method ‘back-to-back’. Here are a few examples or some surprises.

If I try to read the following XML by getting to the tag ‘Connector’, reading the value of the tag of its first child “Num” and then using a While loop to iterate through the remaining children ‘Pin’ and read their value only the first ‘Pin’ tag would be seen, the second is always skipped.

And, BTW you can’t include XML in a post :frowning:



 do
 {
     reader.Read();
     pin = Convert.ToInt16(reader.Value);
     pinSet.Pins.Add(pin);
} while (reader.ReadToNextSibling("Pin"));

If I give each ‘Pin’ tag a child named ‘Num’ the code below works however and I am at a loss to understand why the one above does not. I’m sure it is due to my misunderstanding of the side effects of each method, the API docs for the XML reader don’t do a very good job of explaining them though.



 do
 {
     reader.ReadToDescendant("Num");
     pin = Convert.ToInt16(reader.ReadElementString());
     pinSet.Pins.Add(pin);
} while (reader.ReadToNextSibling("Pin"));

‘Connector’
‘Num’ 2 ‘/Num’
‘Pin’
‘Num ’ 1 ‘/Num’
’/Pin’
‘Pin’
‘Num ’ 2 ‘/Num’
’/Pin’
’/Connector’

OK, after writing the question above I tried a few more things and got it to work with the first method.

After a XMLReader.Read the reader is pointed at the element’s end tag, this will cause ReadToNextSibling to fail. If you add another XMLReader.Read in to advance past the end tag then it works fine.

               
 do
{
    reader.Read();
    pin = Convert.ToInt16(reader.Value);
    pinSet.Pins.Add(pin);
    reader.Read();
} while (reader.ReadToNextSibling("Pin"));

Another way to do the same things is to use XMLReader.ReadString(). It leaves the reader past the end tag of the element that you just read from.


do
{
    pin = Convert.ToInt16(reader.ReadString());
    pinSet.Pins.Add(pin);
} while (reader.ReadToNextSibling("Pin"));