<?xml version="1.0" encoding="utf-8"?> <!-- Generate appropriately numbered and labelled section titles. --> <stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Sections, subsections, subsubsections, ... @label: A label that can be used for cross referencing. Any value can be used, as long as it's a legal identifier in both LaTeX and HTML. @number: Whether or not to generate a section number. It makes the most logical sense for this attribute to be associated with the section element, but the section numbers are actually generated in the "section-title" template (see below). Consequently, this attribute isn't even mentioned in this template. 'yes' [default] 'no' --> <template name="section" match="section"> <common formats="/latex/xelatex/"> <xsl:apply-templates> <xsl:with-param name="label"> <xsl:value-of select="@label" /> <xsl:if test="not( @label )">THERE_IS_NO_LABEL</xsl:if> </xsl:with-param> </xsl:apply-templates> </common> <common formats="/html/xhtml/"> <xsl:if test="@label"><a id="{@label}"></a></xsl:if> <xsl:apply-templates /> </common> </template> <!-- Utility template to generate some number of "sub"s so we can produce, e.g., "subsubsection" for LaTeX. $depth: the number of repetitions (0 to 2). If zero, then the loop never executes. --> <template name="generate-subs"> <common formats="/latex/xelatex/"> <xsl:param name="depth">0</xsl:param> <xsl:for-each select="1 to $depth"> <xsl:text>sub</xsl:text> </xsl:for-each> </common> </template> <!-- Generate a section title with correctly nested numbering, e.g., 1.1.3. If we were being pedantic, this should probably go in titling.xml, but I think it makes more sense here. --> <template name="section-title" match="section/title"> <common formats="/latex/xelatex/"> <xsl:param name="label" /> <!-- Calculate the nesting depth up front, so that we can limit it to 2 for LaTeX. Note that we have to skip counting the parent <section> element, as that's the section currently being processed. Including it would produce a minimum depth of 1, but the minimum depth in LaTeX is actually 0. --> <xsl:variable name="depth"> <xsl:number value="min( ( count( ../ancestor::section ), 2 ) )" /> </xsl:variable> <xsl:text>\</xsl:text> <!-- Generate the correct number of "sub"s for LaTeX. --> <xsl:call-template name="generate-subs"> <xsl:with-param name="depth" select="$depth" /> </xsl:call-template> <xsl:text>section</xsl:text> <!-- Unnumbered section. We reference the @number attribute of the parent <section> element. (We are guaranteed that the parent is a <section> element by the match context for this template.) --> <xsl:if test="../@number = ('no', 'n', 'false', 'f', '0')"> <xsl:text>*</xsl:text> </xsl:if> <xsl:text>{</xsl:text> <xsl:apply-templates /><xsl:text>}</xsl:text> <xsl:if test="$label ne 'THERE_IS_NO_LABEL'"> \label{<xsl:value-of select="$label" />} </xsl:if> </common> <common formats="/html/xhtml/"> <!-- Calculate the nesting depth up front, so that we can limit it to 6 for HTML. Add 1 because <h1> is reserved for the main document title; section headings start at <h2>. --> <xsl:variable name="depth"> <xsl:number value="min( ( 1 + count( ancestor::section ), 6 ) )" /> </xsl:variable> <!-- Generate the correct level of <Hn> element based on the value of $depth. Note the use of an attribute value template to force XSLT to interpret the contents of the name attribute as a function call rather than as the element name. --> <xsl:element name="{concat( 'h', $depth )}"> <!-- Unnumbered section, as per above. Note that the sense of the test is reversed: with LaTeX we output _additional_ text to get an unnumbered section, where as with HTML, we _suppress_ the additional text (i.e., the section number, which is generated here). We also only count sections that _are_ numbered. --> <xsl:if test="not(../@number) or (../@number ne 'no')"> <xsl:number count="section[not(@number) or (@number ne 'no')]" level="multiple" format="1.1.1.1.1.1" /> <xsl:text> </xsl:text> </xsl:if> <xsl:apply-templates /> </xsl:element> </common> </template> </stylesheet>