1<html><head>
2      <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
3   <title>Customizing DocBook XSL stylesheets</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="ch01s03.html" title="XSL processing model"><link rel="next" href="extensions.html" title="Chapter 2. Saxon Extensions"></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">Customizing DocBook XSL stylesheets</th></tr><tr><td width="20%" align="left"><a href="ch01s03.html">Prev</a>&nbsp;</td><th width="60%" align="center">Chapter 1. DocBook XSL</th><td width="20%" align="right">&nbsp;<a href="extensions.html">Next</a></td></tr></table><hr></div><p>The DocBook XSL stylesheets are written in a modular
4fashion. Each of the HTML and FO stylesheets starts with a
5driver file that assembles a collection of component files
6into a complete stylesheet. This modular design puts similar things together into smaller files that are easier to write and maintain than one big stylesheet. The modular stylesheet files
7are distributed among four directories:</p><div class="variablelist"><dl><dt><a name="c44b1b3b7b3b1"></a><span class="term">common/</span></dt><dd><p><a name="c44b1b3b7b3b1b2"></a>contains code common to both stylesheets, including localization data
8</p></dd><dt><a name="c44b1b3b7b3b2"></a><span class="term">fo/</span></dt><dd><p><a name="c44b1b3b7b3b2b2"></a>a stylesheet that produces XSL FO result trees
9</p></dd><dt><a name="c44b1b3b7b3b3"></a><span class="term">html/</span></dt><dd><p><a name="c44b1b3b7b3b3b2"></a>a stylesheet that produces HTML/XHTML result trees
10</p></dd><dt><a name="c44b1b3b7b3b4"></a><span class="term">lib/</span></dt><dd><p><a name="c44b1b3b7b3b4b2"></a>contains schema-independent functions
11</p></dd></dl></div><p>The driver files for each of HTML and FO stylesheets
12are <tt>html/docbook.xsl</tt> and <tt>fo/docbook.xsl</tt>,
13respectively. A driver file consists mostly of a bunch
14of <tt>&lt;xsl:include&gt;</tt> instructions to
15pull in the component templates, and then defines some
16top-level templates. For example:</p><pre class="programlisting">&lt;xsl:include href="/VERSION"/&gt;
17&lt;xsl:include href="/lib/lib.xsl"/&gt;
18&lt;xsl:include href="/common/l10n.xsl"/&gt;
19&lt;xsl:include href="/common/common.xsl"/&gt;
20&lt;xsl:include href="autotoc.xsl"/&gt;
21&lt;xsl:include href="lists.xsl"/&gt;
22&lt;xsl:include href="callout.xsl"/&gt;
23...
24&lt;xsl:include href="param.xsl"/&gt;
25&lt;xsl:include href="pi.xsl"/&gt;
26</pre><p>The first four modules are shared with the FO
27stylesheet and are referenced using relative pathnames to
28the common directories. Then the long list of component
29stylesheets starts. Pathnames in include statements are
30always taken to be relative to the including file. Each
31included file must be a valid XSL stylesheet, which means
32its root element must
33be <tt>&lt;xsl:stylesheet&gt;</tt>.</p><div class="sect2"><a name="c44b1b3b7b7"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b7b7"></a>Stylesheet inclusion vs. importing</h3></div></div><p>XSL actually provides two inclusion
34mechanisms: <tt>&lt;xsl:include&gt;</tt> and <tt>&lt;xsl:import&gt;</tt>.
35Of the two, <tt>&lt;xsl:include&gt;</tt> is
36the simpler. It treats the included content as if it were
37actually typed into the file at that point, and doesn't
38give it any more or less precedence relative to the
39surrounding text. It is best used when assembling
40dissimilar templates that don't overlap what they match.
41The DocBook driver files use this instruction to assemble a
42set of modules into a stylesheet.</p><p>In contrast, <tt>&lt;xsl:import&gt;</tt> lets
43you manage the precedence of templates and variables. It is
44the preferred mode of customizing another stylesheet because
45it lets you override definitions in the distributed
46stylesheet with your own, without altering the distribution
47files at all. You simply import the whole stylesheet and
48add whatever changes you want.</p><p>The precedence rules for import are detailed and
49rigorously defined in the XSL standard. The basic rule is
50that any templates and variables in the importing
51stylesheet have precedence over equivalent templates and
52variables in the imported stylesheet. Think of the imported stylesheet elements as a fallback collection, to be used only if a match is not found in the current stylesheet. You can customize the templates you want to change in your stylesheet file, and let the imported stylesheet handle the rest.</p><div class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title"><a name="c44b1b3b7b7b5"></a>Note</h3><p>Customizing a DocBook XSL stylesheet is the opposite
53of customizing a DocBook DTD. When you customize a DocBook
54DTD, the rules of XML and SGML dictate that
55the <i>first</i> of any duplicate declarations
56wins. Any subsequent declarations of the same element or
57entity are ignored. The architecture of the DTD provides
58slots for inserting your own custom declarations early
59enough in the DTD for them to override the standard
60declarations. In contrast, customizing an XSL stylesheet is
61simpler because your definitions have precedence over imported ones.</p></div><p>You can carry modularization to deeper levels because
62module files can also include or import other modules.
63You'll need to be careful to maintain the precedence that
64you want as the modules get rolled up into a complete
65stylesheet. </p></div><div class="sect2"><a name="c44b1b3b7b8"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b7b8"></a>Customizing
66with <tt>&lt;xsl:import&gt;</tt></h3></div></div><p>There is currently one example of customizing
67with <tt>&lt;xsl:import&gt;</tt> in the HTML
68version of the DocBook stylesheets.
69The <tt>xtchunk.xsl</tt> stylesheet modifies the
70HTML processing to output many smaller HTML files rather
71than a single large file per input document. It uses XSL
72extensions defined only in the XSL
73processor <b>XT</b>. In the driver
74file <tt>xtchunk.xsl</tt>, the first instruction
75is <tt>&lt;xsl:import
76href="docbook.xsl"/&gt;</tt>. That instruction imports
77the original driver file, which in turn uses
78many <tt>&lt;xsl:include&gt;</tt> instructions to
79include all the modules. That single import instruction
80gives the new stylesheet the complete set of DocBook
81templates to start with.</p><p>After the
82import, <tt>xtchunk.xsl</tt> redefines some of
83the templates and adds some new ones. Here is one example
84of a redefined template:</p><pre class="programlisting">Original template in autotoc.xsl
85&lt;xsl:template name="href.target"&gt;
86  &lt;xsl:param name="object" select="."/&gt;
87  &lt;xsl:text&gt;#&lt;/xsl:text&gt;
88  &lt;xsl:call-template name="object.id"&gt;
89    &lt;xsl:with-param name="object" select="$object"/&gt;
90  &lt;/xsl:call-template&gt;
91&lt;/xsl:template&gt;
92
93New template in xtchunk.xsl
94&lt;xsl:template name="href.target"&gt;
95  &lt;xsl:param name="object" select="."/&gt;
96  &lt;xsl:variable name="ischunk"&gt;
97    &lt;xsl:call-template name="chunk"&gt;
98      &lt;xsl:with-param name="node" select="$object"/&gt;
99    &lt;/xsl:call-template&gt;
100  &lt;/xsl:variable&gt;
101
102  &lt;xsl:apply-templates mode="chunk-filename" select="$object"/&gt;
103
104  &lt;xsl:if test="$ischunk='0'"&gt;
105    &lt;xsl:text&gt;#&lt;/xsl:text&gt;
106    &lt;xsl:call-template name="object.id"&gt;
107      &lt;xsl:with-param name="object" select="$object"/&gt;
108    &lt;/xsl:call-template&gt;
109  &lt;/xsl:if&gt;
110&lt;/xsl:template&gt;
111</pre><p>The new template handles the more complex processing
112of HREFs when the output is split into many HTML files.
113Where the old template could simply
114output <tt>#<i><tt>object.id</tt></i></tt>,
115the new one outputs <tt><i><tt>filename</tt></i>#<i><tt>object.id</tt></i></tt>.</p></div><div class="sect2"><a name="c44b1b3b7b9"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b7b9"></a>Setting stylesheet variables</h3></div></div><p>You may not have to define any new templates,
116however. The DocBook stylesheets are parameterized using
117XSL variables rather than hard-coded values for many of the
118formatting features. Since
119the <tt>&lt;xsl:import&gt;</tt> mechanism also
120lets you redefine global variables, this gives you an easy
121way to customize many features of the DocBook
122stylesheets. Over time, more features will be parameterized to permit customization. If you find hardcoded values in the stylesheets that would be useful to customize, please let the maintainer know.</p><p>Near the end of the list of includes in the main
123DocBook driver file is the
124instruction <tt>&lt;xsl:include
125href="param.xsl"/&gt;</tt>.
126The <tt>param.xsl</tt> file is the most
127important module for customizing a DocBook XSL stylesheet.
128This module contains no templates, only definitions of
129stylesheet variables. Since these variables are defined
130outside of any template, they are global variables and
131apply to the entire stylesheet. By redefining these
132variables in an importing stylesheet, you can change the
133behavior of the stylesheet.</p><p>To create a customized DocBook stylesheet, you simply
134create a new stylesheet file such
135as <tt>mystyle.xsl</tt> that imports the standard
136stylesheet and adds your own new variable definitions. Here
137is an example of a complete custom stylesheet that changes
138the depth of sections listed in the table of contents from
139two to three:</p><pre class="programlisting">&lt;?xml version='1.0'?&gt;
140&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
141                version='1.0'
142                xmlns="http://www.w3.org/TR/xhtml1/transitional"
143                exclude-result-prefixes="#default"&gt;
144
145&lt;xsl:import href="docbook.xsl"/&gt;
146
147&lt;xsl:variable name="toc.section.depth"&gt;3&lt;/xsl:variable&gt;
148&lt;!-- Add other variable definitions here --&gt;
149
150&lt;/xsl:stylesheet&gt;
151</pre><p>Following the opening stylesheet element are the
152import instruction and one variable definition. The
153variable <tt>toc.section.depth</tt> was defined
154in <tt>param.xsl</tt> with value "2", and here
155it is defined as "3". Since the importing stylesheet takes
156precedence, this new value is used. Thus documents
157processed with <tt>mystyle.xsl</tt> instead
158of <tt>docbook.xsl</tt> will have three levels
159of sections in the tables of contents, and all other
160processing will be the same.</p><p>Use the list of variables
161in <tt>param.xsl</tt> as your guide for creating
162a custom stylesheet. If the changes you want are controlled
163by a variable there, then customizing is easy. </p></div><div class="sect2"><a name="c44b1b3b7c10"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b7c10"></a>Writing your own templates</h3></div></div><p>If the changes you want are more extensive than what
164is supported by variables, you can write new templates. You
165can put your new templates directly in your importing
166stylesheet, or you can modularize your importing stylesheet
167as well. You can write your own stylesheet module
168containing a collection of templates for processing lists,
169for example, and put them in a file
170named <tt>mylists.xsl</tt>. Then your importing
171stylesheet can pull in your list templates with
172a <tt>&lt;xsl:include
173href="mylists.xsl"/&gt;</tt> instruction. Since your
174included template definitions appear after the main import
175instruction, your templates will take precedence.</p><p>You'll need to make sure your new templates are
176compatible with the remaining modules, which means:</p><div class="itemizedlist"><ul><li><p><a name="c44b1b3b7c10b4b1"></a>Any named templates should use the same name so
177calling templates in other modules can find them.</p></li><li><p><a name="c44b1b3b7c10b4b2"></a>Your template set should process the same elements
178matched by templates in the original module, to ensure
179complete coverage.</p></li><li><p><a name="c44b1b3b7c10b4b3"></a>Include the same set
180of <tt>&lt;xsl:param&gt;</tt> elements in each
181template to interface properly with any calling templates,
182although you can set different values for your
183parameters.</p></li><li><p><a name="c44b1b3b7c10b4b4"></a>Any templates that are used like subroutines to
184return a value should return the same data type.</p></li></ul></div></div><div class="sect2"><a name="c44b1b3b7c11"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b7c11"></a>Writing your own driver</h3></div></div><p>Another approach to customizing the stylesheets is to
185write your own driver file. Instead of
186using <tt>&lt;xsl:import
187href="docbook.xsl"/&gt;</tt>, you copy that file to a
188new name and rewrite any of
189the <tt>&lt;xsl:include/&gt;</tt> instructions to
190assemble a custom collection of stylesheet modules. One
191reason to do this is to speed up processing by reducing the
192size of the stylesheet. If you are using a customized
193DocBook DTD that omits many elements you never use, you
194might be able to omit those modules of the
195stylesheet.</p></div><div class="sect2"><a name="c44b1b3b7c12"></a><div class="titlepage"><div><h3 class="title"><a name="c44b1b3b7c12"></a>Localization</h3></div></div><p>The DocBook stylesheets include features for
196localizing generated text, that is, printing any generated
197text in a language other than the default English. In
198general, the stylesheets will switch to the language
199identified by a <tt>lang</tt> attribute when
200processing elements in your documents. If your documents
201use the <tt>lang</tt> attribute, then you don't
202need to customize the stylesheets at all for
203localization.</p><p>As far as the stylesheets go,
204a <tt>lang</tt> attribute is inherited by the
205descendents of a document element. The stylesheet searches
206for a <tt>lang</tt> attribute using this XPath
207expression:</p><pre class="programlisting">&lt;xsl:variable name="lang-attr"
208         select="($target/ancestor-or-self::*/@lang
209                  |$target/ancestor-or-self::*/@xml:lang)[last()]"/&gt;</pre><p>This locates the attribute on the current element or
210its most recent ancestor. Thus
211a <tt>lang</tt> attribute is in effect for an
212element and all of its descendents, unless it is reset in
213one of those descendents. If you define it in only your
214document root element, then it applies to the whole
215document:</p><pre class="programlisting">&lt;?xml version="1.0"?&gt;
216&lt;!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.0//EN" "docbook.dtd"&gt;
217&lt;book lang="fr"&gt;
218...
219&lt;/book&gt;</pre><p>When text is being generated, the stylesheet checks
220the most recent <tt>lang</tt> attribute and looks
221up the generated text strings for that language in a
222localization XML file. These are located in
223the <tt>common</tt> directory of the
224stylesheets, one file per language. Here is the top of the
225file <tt>fr.xml</tt>:</p><pre class="programlisting">&lt;localization language="fr"&gt;
226
227&lt;gentext key="abstract"                 text="R&amp;#x00E9;sum&amp;#x00E9;"/&gt;
228&lt;gentext key="answer"                   text="R:"/&gt;
229&lt;gentext key="appendix"                 text="Annexe"/&gt;
230&lt;gentext key="article"                  text="Article"/&gt;
231&lt;gentext key="bibliography"             text="Bibliographie"/&gt;
232...
233</pre><p>The stylesheet templates use the gentext key names,
234and then the stylesheet looks up the associated text value
235when the document is processed with that lang setting. The
236file <tt>l10n.xml</tt> (note
237the <tt>.xml</tt> suffix) lists the filenames of
238all the supported languages.</p><p>You can also create a custom stylesheet that sets the
239language. That might be useful if your documents don't make
240appropriate use of the <tt>lang</tt> attribute.
241The module <tt>l10n.xsl</tt> defines two global
242variables that can be overridden with an importing
243stylesheet as described above. Here are their default
244definitions:</p><pre class="programlisting">&lt;xsl:variable name="l10n.gentext.language"&gt;&lt;/xsl:variable&gt;
245&lt;xsl:variable name="l10n.gentext.default.language"&gt;en&lt;/xsl:variable&gt;
246</pre><p>The first one sets the language for all elements,
247regardless of an element's <tt>lang</tt> attribute
248value. The second just sets a default language for any
249elements that haven't got a <tt>lang</tt> setting
250of their own (or their ancestors).</p></div><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a href="ch01s03.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="extensions.html">Next</a></td></tr><tr><td width="40%" align="left">XSL processing model&nbsp;</td><td width="20%" align="center"><a href="publishing.html">Up</a></td><td width="40%" align="right">&nbsp;Chapter 2. Saxon Extensions</td></tr></table></div></body></html>