Customizing cross references

DocBook has two kinds of cross references: those that are empty and those that provide their own text. The empty cross reference elements (xref and empty olink) have their text generated by the stylesheets. The generated text can be customized.

There are two levels of customizing the generated text for cross references:

The xrefstyle feature became available in version 1.62 of the stylesheets and version 4.3 of the DocBook DTD. If you are using an earlier version of the DTD, then you could use the role attribute instead (see the section “Using role instead of xrefstyle”). If you are using an earlier version of the stylesheets, then you can only modify the stylesheet's gentext templates.

Modifying gentext templates

You customize cross reference text by modifying gentext strings for your locale in your customization layer. See the section “Generated text” for a general description of customizing generated text. For cross references, you want to look for gentext templates in one of the xref contexts in the language file you are working with, such as common/en.xml. These are the xref contexts (as of version 1.62 of the stylesheets) and when they apply:

ContextGenerates:Applies to:
context="xref"The element's title.Cross references to elements that are not numbered. Includes chapters when the parameter chapter.autolabel is set to zero. Same with appendix, part, preface, and section elements and their respective parameters.
context="xref-number"The element's number label, such as Chapter 3.Cross references to elements that are numbered, such as chapter, appendix, figure, table. Also applies to sections when they are numbered. Used when the stylesheet parameter xref.with.number.and.title is set to zero.
context="xref-number-and-title"The element's number label and title.Cross references to elements that are numbered, such as chapter, appendix, figure, table. Also applies to sections when they are numbered. Used when the stylesheet parameter xref.with.number.and.title is set to 1 (default).

For example, the common/en.xml file includes the following gentext templates. The text for chapter is highlighted in each context.

<l:context name="xref">
   <l:template name="abstract" text="%t"/>
   <l:template name="appendix" text="%t"/>
   <l:template name="chapter" text="%t"/>
   ...
</l:context>
<l:context name="xref-number">
   <l:template name="appendix" text="Appendix&#160;%n"/>
   <l:template name="chapter" text="Chapter&#160;%n"/> (&#160; is a non-breaking space)
   ...
</l:context>
<l:context name="xref-number-and-title">
   <l:template name="appendix" text="Appendix&#160;%n, %t"/>
   <l:template name="chapter" text="Chapter&#160;%n, %t"/>
   ...
</l:context>
   ...

Each DocBook element that can generate text has a l:template element within each context that can apply. The text attribute value is used to generate the output for a cross reference to that element. The %t placeholder resolves to the target element's title, and %n resolves to its number (if it is numbered).

For example, an xref that points to a chapter would normally generate text like Chapter 3, Using a Mouse (the non-breaking space was replaced for clarity). The context="xref-number-and-title" template is used because chapters are numbered and the stylesheet parameter xref.with.number.and.title is set to 1 by default. If you set xref.with.number.and.title to zero, then the context="xref-number" template is used instead. If you set chapter.autolabel to zero to turn off chapter numbering, then the context="xref" template is used.

To customize cross references, you add new gentext templates to your customization layer that override the stock templates. You have to make sure you cover all the targets elements you reference, and in all the contexts that you use.

For example, if you prefer to use a colon and quotes in cross references to chapters and appendixes, you can add the following to your customization layer:

<xsl:param name="local.l10n.xml" select="document('')"/> 
<l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"> 
  <l:l10n language="en"> 
    <l:context name="xref-number-and-title"> 
      <l:template name="appendix" text="Appendix %n: &#8220;%t&#8221;"/> 
      <l:template name="chapter" text="Chapter %n: &#8220;%t&#8221;"/> 
    </l:context>    
  </l:l10n>
</l:i18n>

If you want to do this for French as well as English, you'll need the following:

<xsl:param name="local.l10n.xml" select="document('')"/> 
<l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"> 
  <l:l10n language="en"> 
    <l:context name="xref-number-and-title"> 
      <l:template name="appendix" text="Appendix %n: &#8220;%t&#8221;"/> 
      <l:template name="chapter" text="Chapter %n: &#8220;%t&#8221;"/> 
    </l:context>    
  </l:l10n>
  <l:l10n language="fr"> 
    <l:context name="xref-number-and-title"> 
      <l:template name="appendix" text="Annexe %n: &#171;%t&#187;"/> 
      <l:template name="chapter" text="Chapitre %n: &#171;%t&#187;"/> 
    </l:context>    
  </l:l10n>
</l:i18n>

The gentext templates are shared by the HTML and FO stylesheets. If you are satisfied that your changes work in both output formats, you can put all of your gentext changes in a separate file and bring them into each of your stylesheet customization layers using:

<xsl:param name="local.l10n.xml" select="document('mygentextmods.xml')"/>

Or if you find you need different cross reference styles for the different output formats, you can keep them as separate modification files.

Customizing with an xrefstyle attribute

Version 4.3 of the DocBook DTD made available an xrefstyle attribute to the xref and olink elements to allow an author to indicate special handling for a single cross reference. Version 1.62 of the stylesheets added support for this new attribute.

The DTD does not specify standard values for the attribute, so stylesheets are free to implement whatever scheme they want. The DocBook XSL stylesheets provide three ways to use the xrefstyle attribute:

  • If the attribute value begins with template: then the rest of the text after the colon is taken to be a gentext template to use for that reference.

  • If the attribute value begins with select: then the author can specify components to make up the generated text using key words defined by the stylesheet.

  • Otherwise the attribute value is taken to be a named cross reference style that is defined in the stylesheet's collection of gentext templates.

Each of these methods is described in more detail in the following sections.

Using "template:"

Text that is generated for cross references comes from gentext templates, in which some of the text is fixed and some is filled in from the title or number of the item being referenced. The stock gentext templates reside in the locale files found in the common subdirectory of the stylesheet distribution, such as common/en.xml for English text. Those templates are described in the section “Modifying gentext templates”.

If an xrefstyle attribute starts with the literal string template: then whatever text appears after the colon is taken to be the gentext template for that reference. This option lets you mix any text with a number label and/or title for the cross reference. Here is an example.

Input:
See <xref linkend="UsingMouse" 
      xrefstyle="template:the chapter numbered %n"/>
for more information.

HTML output:
See <a href="#UsingMouse">the chapter numbered 3</a>
for more information.

The highlighted text is used as the gentext template. The %n is replaced by the chapter number during processing. You could use %t if you want to include the chapter title in a gentext template. Since the text is entered as an attribute value, you cannot include DocBook tags with it. You can include text entities, though. Keep in mind that if the document is translated to other languages, then any regular words in the attribute will have be translated too. Normally translators would not look in attribute values for words to translate.

Using "select:"

A somewhat more structured customization is available when you start an xrefstyle attribute with the literal select: string. This option lets you choose the components that make up the generated text. You specify one or more keywords that are defined in the stylesheet, and the stylesheet then assembles a temporary gentext template for that reference. For example:

Input:
<xref linkend="MouseButtons" 
      xrefstyle="select: labelnumber quotedtitle"/>

HTML output:
<a href="#MouseButtons">2.1: "Using Mouse Buttons"</a>

The stylesheet constructs a gentext template based on the keywords labelnumber and quotedtitle. In this scheme, there are three possible components to the generated text, and each has several possible keywords. This table summarizes the keywords.

Table 14.1. Keywords for xrefstyle select:

ComponentKeywordExampleDescription
number labellabelTable 3Complete label name and number
labelnameTableJust the label name
labelnumber3Just the label number
titletitleUsing a MouseTitle without quotes
quotedtitle"Using a Mouse"Title in quotes
page numberunspecified[12]Stock page citation when insert.xref.page.number parameter set to yes
page(page 12)Page number in parentheses
PagePage 12Capitalized page label
pageabbrev(p. 12)Abbreviated label in parentheses
pagenumber12Just the page number
nopage Turn off page number when insert.xref.page.number parameter set to yes

Note these features:

  • You can specify zero or one keyword for each component type. If a component does not have a keyword, then it is omitted from the output.

  • Although the keywords can be specified in any order, the presentation order in the output is always label, title, and page.

  • Page numbers are generated only for print output, not HTML output.

  • The overall control of page references in print output is set by the insert.xref.page.number stylesheet parameter. It has three possible values:

    no

    Page number references are not included in the output. This is the default value, so you must reset this parameter to get any page cross references in your print output.

    yes

    Page number references are included for each xref instance. If the style is not specified with an xrefstyle attribute, then the stock page citation style is used (see the table above).

    maybe

    A page number reference is output only for each xref with a page component in its xrefstyle attribute.

  • If you want page references on most of your xref elements, then set insert.xref.page.number to yes and turn off individual instances with a nopage keyword in its xrefstyle attribute. If you want page references on only a few xref elements, then set insert.xref.page.number to maybe and add an xrefstyle attribute with a page component to those few instances.

  • If you want to globally change the default page citation style from [12] to something else, then customize the page.citation gentext entry (see the section “Customizing generated text” for details on customizing gentext entries). This example changes the default style to (p. 12):

    <xsl:param name="local.l10n.xml" select="document('')"/>
    <l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
      <l:l10n language="en">
        <l:context name="xref">
          <l:template name="page.citation" text=" (p. %p)"/>
        </l:context>
      </l:l10n>
    </l:i18n>
    

    The %p is the placeholder for the generated page number. If you are translating your documents to other languages, you may need to add similar customizations to the gentext for those languages.

  • The whitespace and punctuation that is inserted between components in the output is specified by these stylesheet parameters:

    xref.label-title.separator

    Used between label and title, if both are specified. Default value is a colon and blank space.

    xref.title-page.separator

    Used between title and page number, if both are specified. Default value is a blank space.

    xref.label-page.separator

    Used between label and page number, if both are specified and a title is not. Default value is a blank space.

  • The label name and quoting characters are taken from the locale files in the common subdirectory of the distribution, so they are appropriate for each language that DocBook supports.

This method is useful when you need a small variation on the standard generated text for a cross reference. It is less raw and more consistent than the ad hoc gentext template used in the template: method for xrefstyle.

Using a named xrefstyle

The two previous methods do not require a stylesheet customization to use them. If you are willing to create and use a stylesheet customization layer, then you can add any number of named gentext templates for cross references to particular target elements. Then you can call such gentext templates by specifying one of the names in an xrefstyle attribute value.

This example adds a style named num-qt (number and quoted title) for sect1 references.

Customization layer:
<xsl:param name="local.l10n.xml" select="document('')"/>
<l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0">
  <l:l10n language="en">
    <l:context name="xref-number-and-title">
      <l:template name="sect1" style="num-qt" text="%n-&#8220;%t&#8221;"/>
    </l:context>
  </l:l10n>
</l:i18n>

Input:
<xref linkend="MouseButtons" xrefstyle="num-qt"/>

HTML output:
<a href="#MouseButtons">2.1-"Using Mouse Buttons"</a>

Note these features:

  • The customization layer uses the method described in the section “Customizing generated text” to add a new gentext template.

  • The new gentext template is similar to the others, but it adds a style="num-qt" attribute to identify the named style.

  • This gentext template applies only to the element identified by the name attribute, which is sect1 in this case. To use this style on other elements you must add a similar gentext template for each element. They can share the same style name.

  • Each gentext template is contained within a language and a context. It will only be used if called on that target element in the same language and context. Keep in mind that there are several possible contexts for xref gentext templates (see the section “Modifying gentext templates”). In this case, if section numbering is not turned on by the section.autolabel stylesheet parameter, then the xref-number-and-title context is not in effect and this template won't be used. You may need to add more gentext templates for a named style in other xref contexts.

This method of customizing xref generated text is most useful when you want a set of standardized styles, and you are willing to invest the time to create the new templates in a customization layer.

Customizing page citations

The print stylesheet provides several options for customizing page references generated by xref elements.

  • You can enable or disable xref page references for the whole document using the insert.xref.page.number parameter, as described in the section “Using "select:"”.

  • If you want to change the default page reference style that uses square brackets, you can customize the gentext template named page.citation, which is in the xref context in the collection of gentext templates. See the section “Modifying gentext templates” for a description of the general process.

  • You can select a particular page reference style for an individual xref in your document by adding an xrefstyle attribute to it, as described in the section “Using "select:"”.

  • If you want to customize the page reference styles that are selected by xrefstyle, then you can customize the gentext templates named page, Page, and pageabbrev. They are also in the xref context in the collection of gentext templates. See the section “Modifying gentext templates” for a description of the general process.

Using role instead of xrefstyle

The xrefstyle attribute was introduced in version 4.3 of the DocBook DTD. If you are using an earlier version of the DTD, then you can use the role attribute instead. When the stylesheet parameter use.role.as.xrefstyle parameter is set to 1 (the default value), then a role attribute on an xref element is treated as if it were an xrefstyle attribute. This means you don't have to upgrade your documents to use DocBook 4.3 or later to use the stylesheet features for customizing cross reference text.

Customizing cross reference typography

Perhaps you want to change the typographical style for the generated text of a cross reference. For example, you might notice that xrefs to chapters italicize the chapter title, but xrefs to sections do not. You might think the gentext templates would let you customize the style, but they don't. The gentext templates specify text in attributes, and attributes are not permitted to have elements in XML. So you can't wrap the gentext in HTML or FO elements for formatting.

You can italicize section titles with a stylesheet customization using the insert.title.markup mode. That mode is used to generate the title to replace the %t placeholder in a gentext template. For FO output, you need to create a template like the following in your customization layer:

<xsl:template  match="sect1|sect2|sect3|sect4|sect5|section"  
               mode="insert.title.markup">
  <xsl:param name="purpose"/>
  <xsl:param name="xrefstyle"/>
  <xsl:param name="title"/>

  <xsl:choose>
    <xsl:when test="$purpose = 'xref'">
      <fo:inline font-style="italic">
        <xsl:copy-of select="$title"/>
      </fo:inline>
    </xsl:when>
    <xsl:otherwise>
      <xsl:copy-of select="$title"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

The mode named insert.title.markup is designed to handle adding markup to titles in a given context. The template parameter named purpose indicates the context. In this case, you want to wrap an inline font-style tag around a section title, but only if the purpose of the title is an xref. That way you don't also italicize these titles in their original location or the table of contents.

If you want something similar for HTML output, just copy this template to your HTML customization layer and replace the fo:inline start and end tags with the equivalent HTML I start and end tags.

If you want to style all cross references in FO output, for xref, link, and ulink references, then a simpler mechanism is available. The xref.properties attribute-set can be used to add FO properties to the text of all such cross references. For example, if you want the cross reference text to appear in blue for ulink elements, then use this customization:

<xsl:attribute-set name="xref.properties">
  <xsl:attribute name="color">
    <xsl:choose>
      <xsl:when test="self::ulink">blue</xsl:when>
      <xsl:otherwise>inherit</xsl:otherwise>
    </xsl:choose>
  </xsl:attribute>
</xsl:attribute-set>

This sets the color property conditionally. When the element using the xref.properties attribute set is a ulink, then the test matches and the color is blue. Otherwise the color is inherited, so there is no color change. Be sure to include the otherwise part. If you want all three cross reference elements to be blue, then you can just set the attribute value without using the choose statement.

For olink elements, the olink.properties attribute-set is available instead. It sets properties on the text generated for olink elements. See Chapter 23, Olinking between documents for more information.

To style all cross references in HTML output, just create a CSS selector on the A element, which is used for all hot links in HTML.