views:

1028

answers:

1

Hi,

I'm implementing the ReadXml() method of IXmlSerializable and I figure using XPath is probably the nicest way to do this.

However, ReadXml() needs to handle the reader position properly.

So given that my WriteXml() produces something like this:

<ObjectName>
  <SubNode>2</SubNode>
  <SubNode>2</SubNode>
</ObjectName>

Is there a better way than (this terrible way) below to ensure the Reader is correctly positioned afterwards?

public override void ReadXml(System.Xml.XmlReader reader)
{
        reader.Read(); /* Read Opening tag */
        /* Using reader.ReadStartElement("ObjectName") reads forward a node,
           i.e. current node becomes the first <SubNode>
           whereas Read() doesn't even when the documentation says they both do 
        */
        XPathNavigator n = MakeXPathNavigator(reader.ReadSubtree());
        XPathNodeIterator nodes = n.Select(".//SubNode");
        while (nodes.MoveNext())
        {
            /* Do stuff with nodes */
            _values.Add(nodes.Current.ValueAsInt);
        }
        reader.Skip(); /* Skip reader forward */
}

public static XPathNavigator MakeXPathNavigator(XmlReader reader)
{
    try
    {
        return new XPathDocument(reader).CreateNavigator();
    }
    catch(XmlException e)
    {
        throw e; /* Maybe hide/deal with exception */
    }
}
+1  A: 

I suspect you might run into some performance issues if using that approach routinely. Since your xml is relatively simple, I strongly suspect that you would do better just using XmlReader directly...

...but doing so isn't easy; IMO, it is better to try to avoid the need to implement IXmlSerializable (juts using regular collection properties etc) - it is a common cause of bugs and frustration.

Marc Gravell
Thanks for the advice. I used XmlReader originally and the code wasn't particularly clear and didn't look like it would handle errors well. Performance isn't a massive issue here and I guess I'd like to wrap my head around what's going on too.
Graphain
I should mention that my example is clairified too - I have to do this for a series of about 20 classes of various degrees of XML complexity.
Graphain
Which is probably even more reason not to use IXmlSerializable, IMO. Getting it right once is a mission; 20 times is heroic. Consider using simple DTO classes that mirror the xml structure, and just translate between the DTO classes and your object model with regular C#.
Marc Gravell
Yeah you're definitely right.
Graphain