Keywords: title, label, numbers

Problem

Your header contains a consecutive number and a title. As you want to style it differently, you need to split it into two pieces.

Solution

The DocBook stylesheets have two modes which are “responsible” for generating the labels and titles: the modes label.markup and title.markup.

To “split” the header, you need to introduce an inline element for styling. For HTML this is span with a class attribute, for XSL-FO it is fo:inline. The principle is the same, but this topic shows only HTML for better readability.

Customize the label.markup and title.markup templates for the specific DocBook element. To simplify the maintenance and customization, use the XSLT <xsl:apply-imports/> tag. This allows you to call the original template without repeating it and to introduce your changes. Save the result from <xsl:apply-imports/> in a variable and only output it, if its value is not empty. The following template shows this approach for a chapter label:

<xsl:template match="d:chapter" mode="label.markup">
  <xsl:variable name="number">
    <xsl:apply-imports/>
  </xsl:variable>

  <xsl:if test="string($number) != ''">
    <span class="number"><xsl:value-of select="$number"/></span>
  </xsl:if>
</xsl:template>

For a chapter title the template is even simpler:

<xsl:template match="d:chapter" mode="title.markup">
  <span class="title">
    <xsl:apply-imports/>
  </span>
</xsl:template>

Apply these changes for all elements that you need to restyle. After you have included these changes in your customization layer, a chapter title in HTML is shown as follows:

<h2 class="title"><a id="id275730"></a>Chapter
  <span class="number">1</span>. <span class="title">...</span>
</h2>

To style the number in bold and the title in a normal weight, use the following CSS rule:

h2.title > .number {
  font-weight: bold;
}
h2.title > .title {
  font-weight: normal;
}

Of course, you can apply all CSS rules you want.

Discussion

Although the customization has some benefits (simple, easy to maintain, support the language files), you should be aware of some issues.

The label.markup and title.markup modes are very basic modes; as such, they are used in other templates as well, not only for titles. This can lead to side effects, which you may or may not want. For example, the modes are used also for the table of contents and for resolving cross-references.

Protecting Cross-References

To prevent the splitting in cross-references, customize the insert.title.markup and insert.label.markup modes as follows:

<xsl:template match="*" mode="insert.label.markup">
  <xsl:param name="purpose"/>
  <xsl:param name="xrefstyle"/>
  <xsl:param name="label"/>

  <xsl:value-of select="$label"/>
</xsl:template>

<xsl:template match="d:chapter" mode="insert.title.markup">
  <xsl:param name="purpose"/>
  <xsl:param name="xrefstyle"/>
  <xsl:param name="title"/>

  <xsl:choose>
    <xsl:when test="$purpose = 'xref'">
      <em><xsl:copy-of select="$title"/></em>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$title"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

The difference between the original and the above customization is the xsl:copy-of tag. In the above customization it is replaced by xsl:value-of. This small change ensures that only the string value is copied, not any elements.

Protecting the Table of Contents

To avoid the same structure in the table of contents, customize the toc.line template as follows:

<xsl:template name="toc.line">
  <xsl:param name="toc-context" select="."/>
  <xsl:param name="depth" select="1"/>
  <xsl:param name="depth.from.context" select="8"/>
  <xsl:variable name="title">
    <xsl:apply-templates select="." mode="titleabbrev.markup"/>
  </xsl:variable>

  <span class="{local-name(.)}">
    <xsl:if test="$autotoc.label.in.hyperlink = 0">
      <xsl:variable name="label">
        <xsl:apply-templates select="." mode="label.markup"/>
      </xsl:variable>
      <xsl:value-of select="$label"/>
      <xsl:if test="$label != ''">
        <xsl:value-of select="$autotoc.label.separator"/>
      </xsl:if>
    </xsl:if>

    <a>
      <xsl:attribute name="href">
        <xsl:call-template name="href.target">
          <xsl:with-param name="context" select="$toc-context"/>
          <xsl:with-param name="toc-context" select="$toc-context"/>
        </xsl:call-template>
      </xsl:attribute>
      <!-- * if $autotoc.label.in.hyperlink is non-zero, then output the label -->
      <!-- * as part of the hyperlinked title -->
      <xsl:if test="not($autotoc.label.in.hyperlink = 0)">
        <xsl:variable name="label">
          <xsl:apply-templates select="." mode="label.markup"/>
        </xsl:variable>
        <xsl:value-of select="$label"/>
        <xsl:if test="$label != ''">
          <xsl:value-of select="$autotoc.label.separator"/>
        </xsl:if>
      </xsl:if>
      <xsl:value-of select="$title"/>
    </a>
  </span>
</xsl:template>

1

Saves the output from <xsl:apply-templates/> in the variable title to use it later

2

Use <xsl:value-of/> to get the string from the label variable

3

Insert the string content of variable title

See Also

.


Project@GitHubIssue#7