Cover Pages Logo SEARCH
Advanced Search
ABOUT
Site Map
CP RSS Channel
Contact Us
Sponsoring CP
About Our Sponsors

NEWS
Cover Stories
Articles & Papers
Press Releases

CORE STANDARDS
XML
SGML
Schemas
XSL/XSLT/XPath
XLink
XML Query
CSS
SVG

TECHNOLOGY REPORTS
XML Applications
General Apps
Government Apps
Academic Apps

EVENTS
LIBRARY
Introductions
FAQs
Bibliography
Technology and Society
Semantics
Tech Topics
Software
Related Standards
Historic

XSLT's Template Dispatch


XSLT's Template Dispatch
 by Clark C. Evans
 December 1, 2000
 XSLT is a language for transforming XML texts. The
 language includes familiar constructs such as for-each
 iteration, conditional statements, and callable
 functions. XSLT also includes an additional control
 structure, the template dispatch, which occurs through
 the interaction of apply-template/select and
 template/match. 
 This paper presents two templates, one of which uses 
 the template dispatch, and a second, functionally equivalent 
 to the first, which is constructed without the help of this 
 control structure. This paper then concludes with a comparison 
 which may help to elucidate the power and elegance of XSLT's
 template dispatch.
 Consider the XML input
<bookcase>
 <book>
 <title>The C Programming Language</title>
 <author>Brian W. Kernighan</author>
 <author>Dennis M. Richie</author>
 </book>
 <book>
 <title>Compilers: Principles, Techniques, and Tools</title>
 <author>Alfred V. Aho</author>
 <author>Ravi Sethi</author>
 <author>Jeffrey D. Ullman</author>
 </book>
</bookcase>
 processed by the XSLT stylesheet
<stylesheet
 xmlns="http://www.w3.org/1999/XSL/Transform"
 version="1.0">
 <template match="author">
 Author: <apply-templates/>
 </template>
 <template match="book">
 Book: <apply-templates select="title|author" />
 </template>
</stylesheet>
 to produce the following output:
 Book: The C Programming Language
 Author: Brian W. Kernighan
 Author: Dennis M. Richie
 Book: Compilers: Principles, Techniques, and Tools
 Author: Alfred V. Aho
 Author: Ravi Sethi
 Author: Jeffrey D. Ullman
 Given any input text, the following stylesheet will
 produce exactly the same output as the stylesheet above,
 only it will do so without the aid of
 apply-template/select and apply-template/match. As a
 consequence, much of its code necessarily emulates
 functionality required by the XSLT specification and
 built into a compliant XSLT processor.
<stylesheet
 xmlns="http://www.w3.org/1999/XSL/Transform"
 version="1.0">
 <template match="/">
 <call-template name="dispatch"/>
 </template>
 <template name="dispatch">
 <variable name="id" select="generate-id(.)" />
 <choose>
 <when test="//author[generate-id(.) = $id]">
 Author: <call-template name="apply" />
 </when>
 <when test="//book[generate-id(.) = $id]">
 Book: <call-template name="apply" >
 <with-param name="select" select="title|author" />
 </call-template>
 </when>
 <when test="self::text()">
 <value-of select="." />
 </when>
 <otherwise>
 <call-template name="apply" />
 </otherwise>
 </choose>
 </template> 
 <template name="apply">
 <param name="select" select="node()" />
 <for-each select="$select">
 <call-template name="dispatch" />
 </for-each>
 </template>
</stylesheet>
 The entry point for a procedural stylesheet is marked by
 <template match="/">, a special case similar to a "C"
 style main() function. When this template is executed,
 the current node for the process is initialized to root
 node, and then the body, <call-template name="dispatch" />, 
 transfers control to the template named dispatch.
 The dispatch template begins by creating a variable,
 $id, which is used to hold an unique string identifier
 generated by the XSLT processor for the current node.
 Following is a conditional switch statement having three
 when clauses and a single otherwise. For each when
 clause, a path expression is evaluated and converted
 into a boolean value. If true, then the corresponding
 body is executed and control resumes immediately after
 the choose construct ends. If all of the when clauses
 fail to fire, then the body of the otherwise is executed.
 The first case, <when
 test="//author[generate-id(.)=$id]">, has a path
 expression returning the node-set consisting of any
 author element having an identifier equal to the current
 node's identifier. Therefore, if the current node
 happens to be an author, the node-set returned will be
 non-empty, which converts to a true boolean value. This
 body is executed with two operations: the non-empty text
 node "\n Author: " is printed and then control is
 transferred to the apply template as specified by
 <call-template name="apply"/>.
 The second case, <when
 test="//book[generate-id(.)=$id]">, is very similar.
 Only here, the apply template is called with a parameter
 named select. The select parameter is the node-set
 containing all element children of the current node with
 a name of either title or author.
 The third case, <when test="self::text()">, only fires
 when the current node is a text node. Here <value-of select=".">
 instructs the processor to print the text value of the current 
 node. Finally, in default, the apply template is called when 
 none of the previous when clauses have executed.
 The last template in the procedural stylesheet, apply,
 has an optional parameter select, which is passed as a
 node-set. If this parameter is missing, then every child
 of the current node is selected. The remainder of this
 function then iterates through the selected node-set,
 calling the dispatch template.
 A comparison of the two stylesheets reveals that the
 first when clause described above corresponds directly
 to the first template of the original stylesheet. In a
 similar manner, the second when clause corresponds to
 the second template of the original stylesheet. The
 third when and the default otherwise clause are needed
 to emulate the built-in-rule required by the XSLT
 specification. A fully compliant emulation would also
 order the tests according to XSLT's priority rules.
 As you can see with this emulation, a good amount of
 code is built into the XSLT processor. Specifically,
 functionality similar to the apply template, a default
 entry point, and a mechanism similar to the dispatch
 template are included. Furthermore, the complexity of
 this dispatch mechanism increases when the import
 statement and mode attribute are considered. The
 administration of these and other details is handled by
 the XSLT processor, allowing succinct stylesheets like
 the first one presented.
 Examination of this procedural stylesheet also clarifies
 the complementary roles played by select and match
 expressions. The select expression chooses which nodes
 to visit, and, for each node, the match expressions
 designate which template to execute. This allows an
 ordered set to be selected as a whole, yet each node in
 the set to be treated individually. This decoupling of
 roles is elegantly managed by the XSLT processor and
 invoked by apply-template/select and template/match.
 The decoupling of select and match also allows a
 processor to pre-compute the match expressions up-front.
 For example, given an in-memory node-based implementation,
 an additional pointer could be added to each node. After 
 the tree is loaded and before processing commences, the 
 processor could visit each node in the tree, filling in 
 a pointer to the template which best matches the node 
 according to the priority rules. Then, while iterating 
 through a selected node-set, the template to dispatch is 
 immediately available without further computation.
 XSLT's template mechanism may not be the best solution
 to every transformation requirement; however, when the
 inputs have varying structure such that relative order
 among nodes with different matching criteria is important, 
 its template dispatch approach is a clear winner.

Prepared by Robin Cover for The XML Cover Pages archive.


[画像:Globe Image]

Document URL: http://xml.coverpages.org/evansTemplateDispatch.html


AltStyle によって変換されたページ (->オリジナル) /