Read XSLT 2.0 and XPath 2.0 Programmer's Reference, 4th Edition Online
Authors: Michael Kay
There's a lot of code here, though nothing especially complicated. One general criticism is that this template rule has grown far too big, which makes it difficult for overlay stylesheets to make modifications; it would be better restructured to use one named template for each of the main output elements. Note that the template rule controls the ordering of items in the result document (for example, the abstract will always precede the status section, regardless of which comes first in the source XML). However, the formatting of each subsection is delegated to a template rule for that particular element. This is therefore a blend of the
navigational
and
rule-based
design patterns. The generation of HTML anchors is also delegated, this time to a named template with parameters. The template looks like this:
which in turn calls:
The anchor template generates an element of the form
id=“NNN”>
. Generating both attributes helps to ensure maximum portability across different browser versions. If the parameter
$conditional
is set to
1
, the template does nothing (actually, it computes an ID value and then ignores it: an example where lazy evaluation will produce performance savings). The actual ID value is taken either from the
@id
attribute of the node passed as a parameter (which defaults to the context node), or from the
$default-id
parameter. Surprisingly, the
$default-id
parameter overrides the
@id
attribute, provided that it is indeed a unique identifier within the source document.
It's instructive to see how much easier this would all be with XSLT 2.0. We could start by rewriting the
object.id
template as a function:
if ($default.id != ‘’ and not($node/key(‘ids’, $default.id))
then $default.id
else if ($node/@id)
then $node/@id”/>
else generate-id($node)”/>
If you prefer, the conditional expression in
select=“($default.id[. != ‘’ and not($node/key(‘ids’,.))],
$node/@id,
generate-id($node))[1]”
The anchor template could also be turned into a function:
and a call on this template, previously written as:
can now be rewritten as:
Apart from reducing the size of the two templates from 14/15 lines to 10 lines or less, the size of the call is reduced from 5 lines to 1, and because the
anchor
template is called 21 times in the stylesheet, this reduces the total size of the stylesheet by 94 lines. (I hope your productivity is not measured by the number of lines of XSLT code that you produce.) Some people argue that verbosity is not a problem in itself, but in my view, if you can see the whole of a template or function on the screen at one time, you are likely to understand its logic more quickly and to make fewer mistakes when you modify it.
The only thing you lose by doing this conversion is the ability of the templates to have default parameters. But I'm not entirely sure this is a great loss: certainly, it's a feature that many languages don't provide.
Creating the Table of Contents
Immediately after the header, the first part of the body of the document is the table of contents. This is generated from within the template rule for the
element, and it is controlled by a parameter
$toc.level
that defines the number of levels in the table of contents; for example, if this is set to
2
, then first- and second-level headings will be listed. HTML cannot produce page numbers, so the table of contents instead contains hyperlinks to the headings of the actual sections.
The
template rule generates the table of contents, and then it uses
toc
, and by generating the headings
Table
of
Contents
,
Appendix
or
Appendices
, and
End
Notes
, as required. There is also provision for referencing appendices that are automatically generated by the stylesheet, for example a glossary or index of error codes.