Dare has been talking recently about the disconnects developers may feel once they make the shift from tree based (XmlDocument) to cursor based (XPathNavigator) model. My personal XML learning curve has started with DOM (I remember those long convolute ugly DOM navigational programs I wrote back in Y2K), then I fell in love with SAX and only then I became XmlReader and XPathNavigator fan. But despite the fact I'm probably not an average developer (as I spend most of my time dealing exclusively with XML) I can feel the disconnect too. DOM is kinda ground zero for many of us and not feeling it underfoot is a bit like flying in zero-gravity. Hurts at first, but fun and cool once you get used to it. I think that's not by accident DOM implemenation in .NET has been named XmlDocument, that reflected some basic attitude at that time, although some of us believe now DOMDocument was a better name.
Anyway, here is my small humble contribution to XPathNavigator appreciation - SerializableXPathNavigator. It's really small wrapper around XPathNavigator, which extends it adding InnerXml/OuterXml properties and WriteTo()/WriteContentTo() methods. That's unfortunate omission XPathNavigator doesn't have such fuctionality in .NET 1.0/1.1 and this fact adds some degree to the discronnect devs feel, because devs do like OuterXml and use it frequently. It's fixed in .NET 2.0, but till then I propose this implementation.
Here is local copy and here is GotDotNet's copy. Free and open source of course.
Usage pattern:
XPathDocument doc = new XPathDocument("books.xml"); XPathNavigator nav = doc.CreateNavigator(); XPathNodeIterator ni = nav.Select("/catalog/book[title='Creepy Crawlies']"); ni.MoveNext(); SerializableXPathNavigator snav = new SerializableXPathNavigator(ni.Current); Console.WriteLine(snav.OuterXml); Console.WriteLine(snav.InnerXml);
Couple of details - SerializableXPathNavigator is XPathNavigator itself, which wraps another XPathNavigator and exposes the following additional members:
OuterXml - gets the XML markup representing the current node and all its child nodes.
InnerXml - gets the XML markup representing only the child nodes of the current node.
WriteTo(XmlWriter) - saves the current node to the specified XmlWriter.
WriteContentTo(XmlWriter) - saves all the child nodes of the current node to the specified XmlWriter.
Implementation details - see sources.
Hope you can find it useful. As usual I appreciate any comments/bugs/critics.
Sorry Dare, I was not aware of that :(
But I think you can still write on this topic in the column, why not?
Yeah, the name sucks...
Oleg,
These are totally killer. I was planning to write these for this month's column of Extreme XML and you've beaten me to it. I dislike the class name but if you don't mind I'd like to link to it in this month's article on passing XML in the CLR.