1<html><head> 2 <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> 3 <title>XSL processing model</title><link rel="stylesheet" href="reference.css" type="text/css"><meta name="generator" content="DocBook XSL Stylesheets V1.37"><link rel="home" href="index.html" title="DocBook XSL Stylesheet Documentation"><link rel="up" href="publishing.html" title="Chapter 1. DocBook XSL"><link rel="previous" href="ch01s02.html" title="A brief introduction to XSL"><link rel="next" href="ch01s04.html" title="Customizing DocBook XSL stylesheets"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><div class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">XSL processing model</th></tr><tr><td width="20%" align="left"><a href="ch01s02.html">Prev</a> </td><th width="60%" align="center">Chapter 1. DocBook XSL</th><td width="20%" align="right"> <a href="ch01s04.html">Next</a></td></tr></table><hr></div><p>XSL is a template language, not a procedural 4language. That means a stylesheet specifies a sample of the 5output, not a sequence of programming steps to generate it. 6A stylesheet consists of a mixture of output samples with 7instructions of what to put in each sample. Each bit of 8output sample and instructions is called 9a <i>template</i>.</p><p>In general, you write a template for each element 10type in your document. That lets you concentrate on 11handling just one element at a time, and keeps a stylesheet 12modular. The power of XSL comes from processing the 13templates recursively. That is, each template handles the 14processing of its own element, and then calls other 15templates to process its children, and so on. Since an XML 16document is always a single root element at the top level 17that contains all of the nested descendent elements, the 18XSL templates also start at the top and work their way down 19through the hierarchy of elements.</p><p>Take the 20DocBook <tt><para></tt> paragraph element as 21an example. To convert this to HTML, you want to wrap the 22paragraph content with the HTML 23tags <tt><p></tt> and <tt></p></tt>. 24But a DocBook <tt><para></tt> can contain 25any number of in-line DocBook elements marking up the text. 26Fortunately, you can let other templates take care of those 27elements, so your XSL template 28for <tt><para></tt> can be quite 29simple:</p><pre class="programlisting"><xsl:template match="para"> 30 <p> 31 <xsl:apply-templates/> 32 </p> 33</xsl:template> 34</pre><p>The <tt><xsl:template></tt> element 35starts a new template, and 36its <tt>match</tt> attribute indicates where to 37apply the template, in this case to 38any <tt><para></tt> elements. The template 39says to output a literal <tt><p></tt> string 40and then execute 41the <tt><xsl:apply-templates/></tt> instruction. 42This tells the XSL processor to look among all the 43templates in the stylesheet for any that should be applied 44to the content of the paragraph. If each template in the 45stylesheet includes 46an <tt><xsl:apply-templates/></tt> instruction, 47then all descendents will eventually be processed. When it 48is through recursively applying templates to the paragraph 49content, it outputs the <tt></p></tt> closing 50tag.</p><div class="sect2"><a name="c44b1b3b6b7"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b6b7"></a>Context is important</h3></div></div><p>Since you aren't writing a linear procedure to 51process your document, the context of where and how to 52apply each modular template is important. 53The <tt>match</tt> attribute 54of <tt><xsl:template></tt> provides that 55context for most templates. There is an entire expression 56language, XPath, for identifying what parts of your 57document should be handled by each template. The simplest 58context is just an element name, as in the example above. 59But you can also specify elements as children of other 60elements, elements with certain attribute values, the first 61or last elements in a sequence, and so on. Here is how the 62DocBook <tt><formalpara></tt> element is 63handled:</p><pre class="programlisting"><xsl:template match="formalpara"> 64 <p> 65 <xsl:apply-templates/> 66 </p> 67</xsl:template> 68 69<xsl:template match="formalpara/title"> 70 <b><xsl:apply-templates/></b> 71 <xsl:text> </xsl:text> 72</xsl:template> 73 74<xsl:template match="formalpara/para"> 75 <xsl:apply-templates/> 76</xsl:template> 77</pre><p>There are three templates defined, one for 78the <tt><formalpara></tt> element itself, 79 and one for each of its children elements. The <tt>match</tt> attribute 80value <tt>formalpara/title</tt> in the second 81template is an XPath expression indicating 82a <tt><title></tt> element that is an 83immediate child of 84a <tt><formalpara></tt> element. This 85distinguishes such titles from 86other <tt><title></tt> elements used in 87DocBook. XPath expressions are the key to controlling how 88your templates are applied.</p><p>In general, the XSL processor has internal rules that 89apply templates that are more specific before templates 90that are less specific. That lets you control the details, 91but also provides a fallback mechanism to a less specific 92template when you don't supply the full context for every 93combination of elements. This feature is illustrated by the 94third template, for <tt>formalpara/para</tt>. By 95including this template, the stylesheet processes a <tt><para></tt> within <tt><formalpara></tt> in 96a special way, in this case by not outputting the HTML <tt><p></tt> tags already output by its parent. If this template had not been included, then the processor would have fallen back to the template 97specified by <tt>match="para"</tt> described 98above, which would have output a second set of <tt><p></tt> tags.</p><p>You can also control template context with 99XSL <i>modes</i>, which are used extensively 100in the DocBook stylesheets. Modes let you process the same 101input more than once in different ways. 102A <tt>mode</tt> attribute in 103an <tt><xsl:template></tt> definition adds a 104specific mode name to that template. When the same mode 105name is used 106in <tt><xsl:apply-templates/></tt>, it acts 107as a filter to narrow the selection of templates to only 108those selected by 109the <tt>match</tt> expression <i>and</i> that 110have that mode name. This lets you define two different 111templates for the same element match that are applied under 112different contexts. For example, there are two templates 113defined for 114DocBook <tt><listitem></tt> elements:</p><pre class="programlisting"><xsl:template match="listitem"> 115 <li><xsl:apply-templates/></li> 116</xsl:template> 117 118<xsl:template match="listitem" mode="xref"> 119 <xsl:number format="1"/> 120</xsl:template> 121</pre><p>The first template is for the normal list item 122context where you want to output the 123HTML <tt><li></tt> tags. The second template 124is called with <tt><xsl:apply-templates 125select="$target" mode="xref"/></tt> in the context 126of processing <tt><xref></tt> elements. In 127this case the <tt>select</tt> attribute locates 128the ID of the specific list item and 129the <tt>mode</tt> attribute selects the second 130template, whose effect is to output its item number when it 131is in an ordered list. Because there are many such special 132needs when 133processing <tt><xref></tt> elements, it is 134convenient to define a mode name <tt>xref</tt> to 135handle them all. Keep in mind that mode settings 136do <i>not</i> automatically get passed down to 137other templates 138through <tt><xsl:apply-templates/></tt>.</p></div><div class="sect2"><a name="c44b1b3b6b8"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b6b8"></a>Programming features</h3></div></div><p>Although XSL is template-driven, it also has some 139features of traditional programming languages. Here are 140some examples from the DocBook stylesheets. </p><pre class="programlisting">Assign a value to a variable: 141<xsl:variable name="refelem" select="name($target)"/> 142 143If statement: 144<xsl:if test="$show.comments"> 145 <i><xsl:call-template name="inline.charseq"/></i> 146</xsl:if> 147 148Case statement: 149<xsl:choose> 150 <xsl:when test="@columns"> 151 <xsl:value-of select="@columns"/> 152 </xsl:when> 153 <xsl:otherwise>1</xsl:otherwise> 154</xsl:choose> 155 156Call a template by name like a subroutine, passing parameter values and accepting a return value: 157<xsl:call-template name="xref.xreflabel"> 158 <xsl:with-param name="target" select="$target"/> 159</xsl:call-template> 160</pre><p>However, you can't always use these constructs as you 161do in other programming languages. Variables in particular 162have very different behavior.</p><div class="sect3"><a name="c44b1b3b6b8b5"></a><div class="titlepage"><div><h4 class="title"><a name="c44b1b3b6b8b5"></a>Using variables and parameters</h4></div></div><p>XSL provides two elements that let you assign a value 163to a 164name: <tt><xsl:variable></tt> and <tt><xsl:param></tt>. 165These share the same name space and syntax for assigning 166names and values. Both can be referred to using 167the <tt>$name</tt> syntax. The main difference 168between these two elements is that a param's value acts as 169a default value that can be overridden when a template is 170called using 171a <tt><xsl:with-param></tt> element as in the 172last example above.</p><p>Here are two examples from DocBook:</p><pre class="programlisting"><xsl:param name="cols">1</xsl:param> 173<xsl:variable name="segnum" select="position()"/> 174</pre><p>In both elements, the name of the parameter or 175variable is specified with 176the <tt>name</tt> attribute. So the name of 177the <tt>param</tt> here 178is <tt>cols</tt> and the name of 179the <tt>variable</tt> is <tt>segnum</tt>. 180The value of either can be supplied in two ways. The value 181of the first example is the text node "1" and is supplied 182as the content of the element. The value of the second 183example is supplied as the result of the expression in 184its <tt>select</tt> attribute, and the element 185itself has no content.</p><p>The feature of XSL variables that is odd to new users 186is that once you assign a value to a variable, you cannot 187assign a new value within the same scope. Doing so will 188generate an error. So variables are not used as dynamic 189storage bins they way they are in other languages. They 190hold a fixed value within their scope of application, and 191then disappear when the scope is exited. This feature is a 192result of the design of XSL, which is template-driven and 193not procedural. This means there is no definite order of 194processing, so you can't rely on the values of changing 195variables. To use variables in XSL, you need to understand 196how their scope is defined.</p><p>Variables defined outside of all templates are 197considered global variables, and they are readable within 198all templates. The value of a global variable is fixed, and 199its global value can't be altered from within any template. 200However, a template can create a local variable of the same 201name and give it a different value. That local value 202remains in effect only within the scope of the local 203variable.</p><p>Variables defined within a template remain in effect 204only within their permitted scope, which is defined as all 205following siblings and their descendants. To understand 206such a scope, you have to remember that XSL instructions 207are true XML elements that are embedded in an XML family 208hierarchy of XSL elements, often referred to as parents, 209children, siblings, ancestors and descendants. Taking the 210family analogy a step further, think of a variable 211assignment as a piece of advice that you are allowed to 212give to certain family members. You can give your advice 213only to your younger siblings (those that follow you) and 214their descendents. Your older siblings won't listen, 215neither will your parents or any of your ancestors. To 216stretch the analogy a bit, it is an error to try to give 217different advice under the same name to the same group of 218listeners (in other words, to redefine the variable). Keep 219in mind that this family is not the elements of your 220document, but just the XSL instructions in your stylesheet. 221To help you keep track of such scopes in hand-written 222stylesheets, it helps to indent nested XSL elements. Here 223is an edited snippet from the DocBook stylesheet 224file <tt>pi.xsl</tt> that illustrates different 225scopes for two variables:</p><pre class="programlisting"> 226 1 <xsl:template name="dbhtml-attribute"> 227 2 ... 228 3 <xsl:choose> 229 4 <xsl:when test="$count>count($pis)"> 230 5 <!-- not found --> 231 6 </xsl:when> 232 7 <xsl:otherwise> 233 8 <xsl:variable name="pi"> 234 9 <xsl:value-of select="$pis[$count]"/> 23510 </xsl:variable> 23611 <xsl:choose> 23712 <xsl:when test="contains($pi,concat($attribute, '='))"> 23813 <xsl:variable name="rest" select="substring-after($pi,concat($attribute,'='))"/> 23914 <xsl:variable name="quote" select="substring($rest,1,1)"/> 24015 <xsl:value-of select="substring-before(substring($rest,2),$quote)"/> 24116 </xsl:when> 24217 <xsl:otherwise> 24318 ... 24419 </xsl:otherwise> 24520 </xsl:choose> 24621 </xsl:otherwise> 24722 </xsl:choose> 24823 </xsl:template> 249 250</pre><p>The scope of the variable <tt>pi</tt> begins 251on line 8 where it is defined in this template, and ends on 252line 20 when its last sibling ends.<sup>[<a name="c44b1b3b6b8b5c10b4" href="#ftn.c44b1b3b6b8b5c10b4">1</a>]</sup> The scope of the 253variable <tt>rest</tt> begins on line 13 and ends 254on line 15. Fortunately, line 15 outputs an expression 255using the value before it goes out of scope.</p><p>What happens when 256an <tt><xsl:apply-templates/></tt> element 257is used within the scope of a local variable? Do the 258templates that are applied to the document children get the 259variable? The answer is no. The templates that are applied 260are not actually within the scope of the variable. They 261exist elsewhere in the stylesheet and are not following 262siblings or their descendants. </p><p>To pass a value to another template, you pass a 263parameter using 264the <tt><xsl:with-param></tt> element. This 265parameter passing is usually done with calls to a specific 266named template 267using <tt><xsl:call-template></tt>, although 268it works 269with <tt><xsl:apply-templates></tt> too. 270That's because the called template must be expecting the 271parameter by defining it using 272a <tt><xsl:param></tt> element with the same 273parameter name. Any passed parameters whose names are not 274defined in the called template are ignored.</p><p>Here is an example of parameter passing 275from <tt>docbook.xsl</tt>:</p><pre class="programlisting"><xsl:call-template name="head.content"> 276 <xsl:with-param name="node" select="$doc"/> 277</xsl:call-template> 278</pre><p>Here a template 279named <tt>head.content</tt> is being called and 280passed a parameter named <tt>node</tt> whose 281content is the value of the <tt>$doc</tt> variable 282in the current context. The top of that template looks like 283this:</p><pre class="programlisting"><xsl:template name="head.content"> 284 <xsl:param name="node" select="."/> 285</pre><p>The template is expecting the parameter because it 286has a <tt><xsl:param></tt> defined with the 287same name. The value in this definition is the default 288value. This would be the parameter value used in the 289template if the template was called without passing that 290parameter.</p></div></div><div class="sect2"><a name="c44b1b3b6b9"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b6b9"></a>Generating HTML output.</h3></div></div><p>You generate HTML from your DocBook XML files by 291applying the HTML version of the stylesheets. This is done 292by using the HTML driver 293file <tt>docbook/html/docbook.xsl</tt> as your 294stylesheet. That is the master stylesheet file that 295uses <tt><xsl:include></tt> to pull in the 296component files it needs to assemble a complete stylesheet 297for producing HTML. </p><p>The way the DocBook stylesheet generates HTML is to 298apply templates that output a mix of text content and HTML 299elements. Starting at the top level in the main 300file <tt>docbook.xsl</tt>:</p><pre class="programlisting"><xsl:template match="/"> 301 <xsl:variable name="doc" select="*[1]"/> 302 <html> 303 <head> 304 <xsl:call-template name="head.content"> 305 <xsl:with-param name="node" select="$doc"/> 306 </xsl:call-template> 307 </head> 308 <body> 309 <xsl:apply-templates/> 310 </body> 311 </html> 312</xsl:template> 313</pre><p>This template matches the root element of your input 314document, and starts the process of recursively applying 315templates. It first defines a variable 316named <tt>doc</tt> and then outputs two literal 317HTML elements <tt><html></tt> and <tt><head></tt>. 318Then it calls a named 319template <tt>head.content</tt> to process the 320content of the HTML <tt><head></tt>, closes 321the <tt><head></tt> and starts 322the <tt><body></tt>. There it 323uses <tt><xsl:apply-templates/></tt> to 324recursively process the entire input document. Then it just 325closes out the HTML file.</p><p>Simple HTML elements can generated as literal 326elements as shown here. But if the HTML being output 327depends on the context, you need something more powerful to 328select the element name and possibly add attributes and 329their values. Here is a fragment 330from <tt>sections.xsl</tt> that shows how a 331heading tag is generated using 332the <tt><xsl:element></tt> and <tt><xsl:attribute></tt> elements:</p><pre class="programlisting"> 333 1 <xsl:element name="h{$level}"> 334 2 <xsl:attribute name="class">title</xsl:attribute> 335 3 <xsl:if test="$level<3"> 336 4 <xsl:attribute name="style">clear: all</xsl:attribute> 337 5 </xsl:if> 338 6 <a> 339 7 <xsl:attribute name="name"> 340 8 <xsl:call-template name="object.id"/> 341 9 </xsl:attribute> 34210 <b><xsl:copy-of select="$title"/></b> 34311 </a> 34412 </xsl:element> 345</pre><p>This whole example is generating a single HTML 346heading element. Line 1 begins the HTML element definition 347by identifying the name of the element. In this case, the 348name is an expression that includes the 349variable <tt>$level</tt> passed as a parameter to 350this template. Thus a single template can 351generate <tt><h1></tt>, <tt><h2></tt>, 352etc. depending on the context in which it is called. Line 2 353defines a <tt>class="title"</tt> attribute that is 354added to this element. Lines 3 to 5 add 355a <tt>style="clear all"</tt> attribute, but only 356if the heading level is less than 3. Line 6 opens 357an <tt><a></tt> anchor element. Although this 358looks like a literal output string, it is actually modified 359by lines 7 to 9 that insert 360the <tt>name</tt> attribute into 361the <tt><a></tt> element. This illustrates 362that XSL is managing output elements as active element 363nodes, not just text strings. Line 10 outputs the text of 364the heading title, also passed as a parameter to the 365template, enclosed in HTML boldface tags. Line 11 closes 366the anchor tag with the 367literal <tt></a></tt> syntax, while line 12 368closes the heading tag by closing the element definition. 369Since the actual element name is a variable, it couldn't 370use the literal syntax.</p><p>As you follow the sequence of nested templates 371processing elements, you might be wondering how the 372ordinary text of your input document gets to the output. In 373the file <tt>docbook.xsl</tt> you will find 374this template that handles any text not processed by any 375other template:</p><pre class="programlisting"><xsl:template match="text()"> 376 <xsl:value-of select="."/> 377</xsl:template> 378</pre><p>This template's body consists of the "value" of the text node, 379which is just its text. In general, all XSL processors have 380some built-in templates to handle any content for which 381your stylesheet doesn't supply a matching template. This 382template serves the same function but appears explicitly in 383the stylesheet.</p></div><div class="sect2"><a name="c44b1b3b6c10"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b6c10"></a>Generating formatting objects.</h3></div></div><p>You generate formatting objects from your DocBook XML 384files by applying the fo version of the stylesheets. This 385is done by using the fo driver 386file <tt>docbook/fo/docbook.xsl</tt> as your 387stylesheet. That is the master stylesheet file that 388uses <tt><xsl:include></tt> to pull in the 389component files it needs to assemble a complete stylesheet 390for producing formatting objects. Generating a formatting 391objects file is only half the process of producing typeset 392output. You also need a formatting object processor such as 393the Apache XML Project's FOP as described in an earlier 394section.</p><p>The DocBook fo stylesheet works in a similar manner 395to the HTML stylesheet. Instead of outputting HTML tags, it 396outputs text marked up 397with <tt><fo:<i><tt>something</tt></i>></tt> tags. 398For example, to indicate that some text should be kept 399in-line and typeset with a monospace font, it might look 400like this:</p><pre class="programlisting"><fo:inline-sequence font-family="monospace">/usr/man</fo:inline-sequence></pre><p>The templates 401in <tt>docbook/fo/inline.xsl</tt> that produce 402this output for a 403DocBook <tt><filename></tt> element look 404like this:</p><pre class="programlisting"><xsl:template match="filename"> 405 <xsl:call-template name="inline.monoseq"/> 406</xsl:template> 407 408<xsl:template name="inline.monoseq"> 409 <xsl:param name="content"> 410 <xsl:apply-templates/> 411 </xsl:param> 412 <fo:inline-sequence font-family="monospace"> 413 <xsl:copy-of select="$content"/> 414 </fo:inline-sequence> 415</xsl:template> 416</pre><p>There are dozens of fo tags and attributes specified 417in the XSL standard. It is beyond the scope of this 418document to cover how all of them are used in the DocBook 419stylesheets. Fortunately, this is only an intermediate 420format that you probably won't have to deal with very much 421directly unless you are writing your own 422stylesheets.</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a href="ch01s02.html">Prev</a> </td><td width="20%" align="center"><a href="index.html">Home</a></td><td width="40%" align="right"> <a href="ch01s04.html">Next</a></td></tr><tr><td width="40%" align="left">A brief introduction to XSL </td><td width="20%" align="center"><a href="publishing.html">Up</a></td><td width="40%" align="right"> Customizing DocBook XSL stylesheets</td></tr></table></div></body></html>