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>&nbsp;</td><th width="60%" align="center">Chapter 1. DocBook XSL</th><td width="20%" align="right">&nbsp;<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>&lt;para&gt;</tt> paragraph element as
21an example. To convert this to HTML, you want to wrap the
22paragraph content with the HTML
23tags <tt>&lt;p&gt;</tt> and <tt>&lt;/p&gt;</tt>.
24But a DocBook <tt>&lt;para&gt;</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>&lt;para&gt;</tt> can be quite
29simple:</p><pre class="programlisting">&lt;xsl:template match="para"&gt;
30  &lt;p&gt;
31    &lt;xsl:apply-templates/&gt;
32  &lt;/p&gt;
33&lt;/xsl:template&gt;
34</pre><p>The <tt>&lt;xsl:template&gt;</tt> element
35starts a new template, and
36its <tt>match</tt> attribute indicates where to
37apply the template, in this case to
38any <tt>&lt;para&gt;</tt> elements. The template
39says to output a literal <tt>&lt;p&gt;</tt> string
40and then execute
41the <tt>&lt;xsl:apply-templates/&gt;</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>&lt;xsl:apply-templates/&gt;</tt> instruction,
47then all descendents will eventually be processed. When it
48is through recursively applying templates to the paragraph
49content, it outputs the <tt>&lt;/p&gt;</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>&lt;xsl:template&gt;</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>&lt;formalpara&gt;</tt> element is
63handled:</p><pre class="programlisting">&lt;xsl:template match="formalpara"&gt;
64  &lt;p&gt;
65    &lt;xsl:apply-templates/&gt;
66  &lt;/p&gt;
67&lt;/xsl:template&gt;
68
69&lt;xsl:template match="formalpara/title"&gt;
70  &lt;b&gt;&lt;xsl:apply-templates/&gt;&lt;/b&gt;
71  &lt;xsl:text&gt; &lt;/xsl:text&gt;
72&lt;/xsl:template&gt;
73
74&lt;xsl:template match="formalpara/para"&gt;
75  &lt;xsl:apply-templates/&gt;
76&lt;/xsl:template&gt;
77</pre><p>There are three templates defined, one for
78the <tt>&lt;formalpara&gt;</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>&lt;title&gt;</tt> element that is an
83immediate child of
84a <tt>&lt;formalpara&gt;</tt> element. This
85distinguishes such titles from
86other <tt>&lt;title&gt;</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>&lt;para&gt;</tt> within <tt>&lt;formalpara&gt;</tt> in
96a special way, in this case by not outputting the HTML <tt>&lt;p&gt;</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>&lt;p&gt;</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>&lt;xsl:template&gt;</tt> definition adds a
104specific mode name to that template. When the same mode
105name is used
106in <tt>&lt;xsl:apply-templates/&gt;</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>&lt;listitem&gt;</tt>  elements:</p><pre class="programlisting">&lt;xsl:template match="listitem"&gt;
115  &lt;li&gt;&lt;xsl:apply-templates/&gt;&lt;/li&gt;
116&lt;/xsl:template&gt;
117
118&lt;xsl:template match="listitem" mode="xref"&gt;
119  &lt;xsl:number format="1"/&gt;
120&lt;/xsl:template&gt;
121</pre><p>The first template is for the normal list item
122context where you want to output the
123HTML <tt>&lt;li&gt;</tt> tags. The second template
124is called with <tt>&lt;xsl:apply-templates
125select="$target" mode="xref"/&gt;</tt> in the context
126of processing <tt>&lt;xref&gt;</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>&lt;xref&gt;</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>&lt;xsl:apply-templates/&gt;</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&lt;xsl:variable name="refelem" select="name($target)"/&gt;
142
143If statement:
144&lt;xsl:if test="$show.comments"&gt;
145    &lt;i&gt;&lt;xsl:call-template name="inline.charseq"/&gt;&lt;/i&gt;
146&lt;/xsl:if&gt;
147
148Case statement:
149&lt;xsl:choose&gt;
150    &lt;xsl:when test="@columns"&gt;
151        &lt;xsl:value-of select="@columns"/&gt;
152    &lt;/xsl:when&gt;
153    &lt;xsl:otherwise&gt;1&lt;/xsl:otherwise&gt;
154&lt;/xsl:choose&gt;
155
156Call a template by name like a subroutine, passing parameter values and accepting a return value:
157&lt;xsl:call-template name="xref.xreflabel"&gt;
158   &lt;xsl:with-param name="target" select="$target"/&gt;
159&lt;/xsl:call-template&gt;
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>&lt;xsl:variable&gt;</tt> and <tt>&lt;xsl:param&gt;</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>&lt;xsl:with-param&gt;</tt> element as in the
172last example above.</p><p>Here are two examples from DocBook:</p><pre class="programlisting">&lt;xsl:param name="cols"&gt;1&lt;/xsl:param&gt;
173&lt;xsl:variable name="segnum" select="position()"/&gt;
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 &lt;xsl:template name="dbhtml-attribute"&gt;
227 2 ...
228 3    &lt;xsl:choose&gt;
229 4       &lt;xsl:when test="$count&gt;count($pis)"&gt;
230 5          &lt;!-- not found --&gt;
231 6       &lt;/xsl:when&gt;
232 7       &lt;xsl:otherwise&gt;
233 8          &lt;xsl:variable name="pi"&gt;
234 9             &lt;xsl:value-of select="$pis[$count]"/&gt;
23510          &lt;/xsl:variable&gt;
23611          &lt;xsl:choose&gt;
23712             &lt;xsl:when test="contains($pi,concat($attribute, '='))"&gt;
23813                &lt;xsl:variable name="rest" select="substring-after($pi,concat($attribute,'='))"/&gt;
23914                &lt;xsl:variable name="quote" select="substring($rest,1,1)"/&gt;
24015                &lt;xsl:value-of select="substring-before(substring($rest,2),$quote)"/&gt;
24116             &lt;/xsl:when&gt;
24217             &lt;xsl:otherwise&gt;
24318             ...
24419             &lt;/xsl:otherwise&gt;
24520          &lt;/xsl:choose&gt;
24621       &lt;/xsl:otherwise&gt;
24722    &lt;/xsl:choose&gt;
24823 &lt;/xsl:template&gt;
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>&lt;xsl:apply-templates/&gt;</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>&lt;xsl:with-param&gt;</tt> element. This
265parameter passing is usually done with calls to a specific
266named template
267using <tt>&lt;xsl:call-template&gt;</tt>, although
268it works
269with <tt>&lt;xsl:apply-templates&gt;</tt> too.
270That's because the called template must be expecting the
271parameter by defining it using
272a <tt>&lt;xsl:param&gt;</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">&lt;xsl:call-template name="head.content"&gt;
276   &lt;xsl:with-param name="node" select="$doc"/&gt;
277&lt;/xsl:call-template&gt;
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">&lt;xsl:template name="head.content"&gt;
284   &lt;xsl:param name="node" select="."/&gt;
285</pre><p>The template is expecting the parameter because it
286has a <tt>&lt;xsl:param&gt;</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>&lt;xsl:include&gt;</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">&lt;xsl:template match="/"&gt;
301  &lt;xsl:variable name="doc" select="*[1]"/&gt;
302  &lt;html&gt;
303  &lt;head&gt;
304    &lt;xsl:call-template name="head.content"&gt;
305      &lt;xsl:with-param name="node" select="$doc"/&gt;
306    &lt;/xsl:call-template&gt;
307  &lt;/head&gt;
308  &lt;body&gt;
309    &lt;xsl:apply-templates/&gt;
310  &lt;/body&gt;
311  &lt;/html&gt;
312&lt;/xsl:template&gt;
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>&lt;html&gt;</tt> and <tt>&lt;head&gt;</tt>.
318Then it calls a named
319template <tt>head.content</tt> to process the
320content of the HTML <tt>&lt;head&gt;</tt>, closes
321the <tt>&lt;head&gt;</tt> and starts
322the <tt>&lt;body&gt;</tt>. There it
323uses <tt>&lt;xsl:apply-templates/&gt;</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>&lt;xsl:element&gt;</tt> and <tt>&lt;xsl:attribute&gt;</tt> elements:</p><pre class="programlisting">
333 1 &lt;xsl:element name="h{$level}"&gt;
334 2   &lt;xsl:attribute name="class"&gt;title&lt;/xsl:attribute&gt;
335 3   &lt;xsl:if test="$level&lt;3"&gt;
336 4     &lt;xsl:attribute name="style"&gt;clear: all&lt;/xsl:attribute&gt;
337 5   &lt;/xsl:if&gt;
338 6   &lt;a&gt;
339 7     &lt;xsl:attribute name="name"&gt;
340 8       &lt;xsl:call-template name="object.id"/&gt;
341 9     &lt;/xsl:attribute&gt;
34210     &lt;b&gt;&lt;xsl:copy-of select="$title"/&gt;&lt;/b&gt;
34311   &lt;/a&gt;
34412 &lt;/xsl:element&gt;
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>&lt;h1&gt;</tt>, <tt>&lt;h2&gt;</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>&lt;a&gt;</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>&lt;a&gt;</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>&lt;/a&gt;</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">&lt;xsl:template match="text()"&gt;
376  &lt;xsl:value-of select="."/&gt;
377&lt;/xsl:template&gt;
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>&lt;xsl:include&gt;</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>&lt;fo:<i><tt>something</tt></i>&gt;</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">&lt;fo:inline-sequence font-family="monospace"&gt;/usr/man&lt;/fo:inline-sequence&gt;</pre><p>The templates
401in <tt>docbook/fo/inline.xsl</tt>      that produce
402this output for a
403DocBook   <tt>&lt;filename&gt;</tt>     element look
404like this:</p><pre class="programlisting">&lt;xsl:template match="filename"&gt;
405  &lt;xsl:call-template name="inline.monoseq"/&gt;
406&lt;/xsl:template&gt;
407
408&lt;xsl:template name="inline.monoseq"&gt;
409  &lt;xsl:param name="content"&gt;
410    &lt;xsl:apply-templates/&gt;
411  &lt;/xsl:param&gt;
412  &lt;fo:inline-sequence font-family="monospace"&gt;
413    &lt;xsl:copy-of select="$content"/&gt;
414  &lt;/fo:inline-sequence&gt;
415&lt;/xsl:template&gt;
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>&nbsp;</td><td width="20%" align="center"><a href="index.html">Home</a></td><td width="40%" align="right">&nbsp;<a href="ch01s04.html">Next</a></td></tr><tr><td width="40%" align="left">A brief introduction to XSL&nbsp;</td><td width="20%" align="center"><a href="publishing.html">Up</a></td><td width="40%" align="right">&nbsp;Customizing DocBook XSL stylesheets</td></tr></table></div></body></html>