And here is another beast for XML bestiary I've created a year ago, but forgot to publish. I'm not sure may be someone did that already, the idea and implementation are really trivial. It's XmlNodeNavigator, which is XPathNavigator over XmlNode (as a subtree) in XmlDocument. It allows to navigate over a subtree in DOM as if it's independent XML document. The main goal of the XmlNodeNavigator is to enable XSL transformation of a portion of XmlDocument without creating temporary XmlDocument containing that portion of data.
Every XSLTers moving from MSXML to .NET usually get stuck with that. In MSXML one usually applies transformation to a node, defining by this the context XSLT operates on. Whenever you want to process only a piece of XML, just run tranformNode() on the node, which encapsulates that piece of data and all XSLT will see then is just that piece of XML, not the whole tree. In .NET though that won't work as XslTransform class applies transformation to the document as a whole, no matter which node you have passed as input. MSDN suggests using temporary XmlDocument, which contains fragment of data you want to transform. That solution is really not satisfactory, pure wasting of memory and performance penalty just for the glory of programmer's laziness. Here is where XmlNodeNavigator idea comes into play. It implements XPathNavigator over the subtree and doesn't allow to navigate outside the subtree boundaries thus enabling effective subtree transformations.
Couple of words about the implementation. XmlNodeNavigator leverages XmlDocument's native XPathNavigator internally, but in MoveTo, MoveToFirst, MoveToNext, MoveToPrevious, MoveToRoot and MoveToParent methods it additionally ensures the navigation doesn't go beyound permissible boundaries - out of the given XmlNode and its descendants. Download XmlNodeNavigator from GotDotNet and see sources for more info.
Finally a sample of transforming XML fragment using XmlNodeNavigator. Source XML:
<library> <book genre='novel' ISBN='1-861001-57-5'> <title>Pride And Prejudice</title> </book> <book genre='novel' ISBN='1-81920-21-2'> <title>Hook</title> </book> </library>And the stylesheet is just copies all available input to output:
<stylesheet version="1.0" xmlns="http://www.w3.org/1999/XSL/Transform" > <output indent="yes"/> <template match="/"> <copy-of select="/"/> </template> </stylesheet>The code:
XslTransform xslt = new XslTransform(); xslt.Load("test.xsl"); XmlDocument doc = new XmlDocument(); doc.Load("foo.xml"); //Navigator over first child of document element XPathNavigator nav = new XmlNodeNavigator(doc.DocumentElement.FirstChild); xslt.Transform(nav, null, Console.Out, null);The result:
<book genre="novel" ISBN="1-861001-57-5"> <title>Pride And Prejudice</title> </book>So, the navigator over first book element has been provided to the transformation and all the XslTransform sees at input is only this subtree - book element and its descendants. And that's done with no any interim tree. It would be really nice to see such class in v2 of System.Xml API.
Leave a comment