Optimization and Partial Transformation

I l @ ve RuBoard

You have now seen how to perform basic transformations in J# applications using XSLT. These types of transformations can take input from various sources and transform it into the appropriate form ”which is sufficient for many uses. But if the transformations form part of critical application logic, this approach can create a performance bottleneck because of the inefficiency of repeated file and string manipulation. To address this, optimizations are required.

Searching and Navigating Using XPath

In Chapter 5, you briefly encountered the XPathNavigator class, which provides read-only access to the nodes in an XML document. You can navigate through these nodes, moving forward and backward as required. An XPathNavigator can be obtained from an XmlDocument , an XmlNode , or from the specialized XPathDocument class. An example of the use of an XPathNavigator , taken from the sample file XPathNavigation.jsl, is shown here:

 XPathDocumentdoc=newXPathDocument(source); XPathNavigatornav=doc.CreateNavigator(); nav.MoveToFirstChild();//Movefromroottodocumentelement nav.MoveToFirstChild();//MovefromdocumentelementtofirstCakeType while(nav.MoveToNext()) { dumpCurrentNode(nav); } Console.WriteLine("Andbackagain!"); while(nav.MoveToPrevious()) { dumpCurrentNode(nav); } 

The XPathNavigator class provides powerful XPath searching capabilities over the XML nodes of its associated document. You can query the XML document and retrieve a set of nodes that match the given query in the form of an XPathNodeIterator , with which you can walk through the retrieved nodes. The following code shows this technique as applied in the sample file XPathIteration.jsl:

 privatestaticvoidsearch(Stringsource,Stringexpression) { XPathDocumentdoc=newXPathDocument(source); XPathNavigatornav=doc.CreateNavigator(); XPathNodeIteratoriterator=nav.Select(expression); while(iterator.MoveNext()) { dumpCurrentNode(iterator.get_Current()); } } 

At this stage, you might be thinking "So what?" This technique gives you similar functionality to the DOM navigation methods and the SelectSingleNode method you saw earlier as part of the XmlDocument class. Well, in terms of searching, the XPathNavigator offers one big advantage over the XmlDocument : you can compile the XPath expression being used to search the document. This offers great performance advantages when the same query is used repeatedly because you can parse the XPath string just once and then use the compiled expression again and again. The use of the Compile method on the XPathNavigator class is shown here:

 XPathDocumentdoc=newXPathDocument(source1); XPathNavigatornav=doc.CreateNavigator(); //Compiletheexpressiontospeedupsubsequentnavigation XPathExpressioncompiledExpr=nav.Compile(expression); XPathNodeIteratoriterator=nav.Select(compiledExpr); while(iterator.MoveNext()) { dumpCurrentNode(iterator.get_Current()); } XPathDocumentdoc2=newXPathDocument(source2); XPathNavigatornav2=doc2.CreateNavigator(); //Re-usethecompiledexpression XPathNodeIteratoriterator2=nav2.Select(compiledExpr); while(iterator2.MoveNext()) { dumpCurrentNode(iterator2.get_Current()); } 

As you can see, the XPath query is compiled once and then used on both the first and second documents. The sample file CompiledXPathIteration.jsl uses the code above to search two cake catalogs using the same XPath expression.

Compiled XPath queries using an XPathNavigator are an efficient way of searching an XML document, but what does this mean for XSLT? Well, you can use the XPathNavigator and its optimizations to speed up XSLT transformations.

Optimizing XSLT Transformations

The Load and Transform methods of the XslTransform class allow you to specify the XML source document and the XSLT stylesheet in the form of XPathNavigator classes. You do this by passing an XPathNavigator or passing a class that implements the IXPathNavigable interface (which requires the class to implement a CreateNavigator method). Providing the source and stylesheet in this way greatly optimizes the transformation process.

As you've seen, the XPathDocument class is another way of representing an XML document. The XPathDocument class does not in itself provide methods for accessing parts of an XML tree. Instead, it allows you to obtain an XPathNavigator on the particular document so you can traverse it. The great advantage of the XPathDocument is that it is a lighter-weight object than a DOM-based XmlDocument . An XPathDocument does not maintain node identity information, nor does it perform all of the rule checking required by the W3C DOM standard. To use XPathDocument classes for both stylesheet and input documents, you can use code as shown in the XPathDocumentTransform.jsl sample file:

 XPathDocumenttransform=newXPathDocument(stylesheet); XslTransformtransformer=newXslTransform(); transformer.Load(transform); XPathDocumentsourceDocument=newXPathDocument(source); transformer.Transform(sourceDocument,null,Console.get_Out()); 

Partial Transformations

In some cases, you might want to simply transform part of a document. In our example, this could be a single CakeType element. However, the transformation of only part of a tree is trickier than you might expect.

For example, if you load the XML into an XmlDocument , an XmlDataDocument , or an XPathDocument and locate the node whose contents you want to transform, you might expect to be able to use the XPathNavigator obtained from this node to transform just the node and its descendents. However, the XPathNavigator obtained in such a way is still an XPathNavigator for the whole document to which this node pertains. Hence, to limit the scope of the XPathNavigator , you must clone the appropriate node, and its descendents, and place the subtree in its own XmlDocumentFragment as follows :

 XPathDocumenttransform=newXPathDocument(stylesheet); XslTransformtransformer=newXslTransform(); transformer.Load(transform); XmlDocumentsourceDocument=newXmlDocument(); sourceDocument.Load(source); XmlDocumentFragmentpartialTree=sourceDocument.CreateDocumentFragment(); 
 partialTree.AppendChild(sourceDocument.SelectSingleNode(expression).Clone()); XPathNavigatornav2=partialTree.CreateNavigator(); transformer.Transform(partialTree,null,Console.get_Out()); 

You use the SelectSingleNode method of the XmlDocument to find the required node, and this node (along with its descendents) is cloned. The cloned node is then appended to an empty XmlDocumentFragment , and an XPathNavigator is obtained from this fragment and passed to the Transform method.

The full code for this conversion can be found in the sample file PartialTransform.jsl.

I l @ ve RuBoard


Microsoft Visual J# .NET (Core Reference)
Microsoft Visual J# .NET (Core Reference) (Pro-Developer)
ISBN: 0735615500
EAN: 2147483647
Year: 2002
Pages: 128

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net