HTML HEAD elements

The HTML HEAD element is used to pass additional information to the browser that is not displayed. There are several DocBook XSL parameters that can add specific items to the HEAD output. There are also three emtpy placeholder templates that you can use in your customization layer. These are described at the end of the section.

The parameters that affect the HEAD content include:

html.base

If this parameter is set to a URL string, the output will include:

<base href="url">

This value establishes the base URL for all relative URLs in the document.

Note that it is not possible to add a target attribute to the base element to set an output window name for the browser.

html.stylesheet

If this parameter is set to the pathname of your CSS stylesheet, then the output will include:

<link rel="stylesheet" href="mystyle.css" 
     type="text/css">

Remember that you must copy the CSS stylesheet to where it is expected to be found relative to the HTML output.

link.mailto.url

If this parameter is set to a mail URI such as mailto:bobs@sagehill.net, then the output will include:

<link rev="made" href="mailto:bobs@sagehill.net">
inherit.keywords

This parameter controls whether a keyword meta element is created in chunked section files. If your document contains a DocBook keywordset element, then the output will automatically include something like the following:

<meta name="keywords" content="word1, word2, word3">

Normally the keywords in a chunked file would only include the ones that appear within its content. If inherit.keywords is set to 1, then the list of keywords in each chunked file will include those from its ancestor elements.

generate.meta.abstract

If this parameter is set to 1, and if your document contains an abstract element, then the output will include something like the following:

<meta name="description" content="text of abstract">

Since content is an attribute, it cannot contain markup, so only the plain text of the abstract is included.

If you need to add other items to the HTML HEAD, there are three user-defined templates you can fill in.

Table 12.2. Templates for HTML HEAD additions

system.head.contentCalled first in the head element.
user.head.contentCalled last in the head element.
user.prerootTemplate called prior to output of html root element. Lets you output processing-instructions or comments, but not elements.

The template named system.head.content is called at the beginning of the HEAD element, before the standard head content is output. That lets you define style attributes that can be overridden by the CSS stylesheet. The user.head.content template is called at the end of the HEAD element, after the standard head content. The following is an example that would add a copyright inside of an HTML comment, and a base element with a target attribute that can be passed as a parameter value:

<xsl:param name="target.window" select="'_self'"/>
<xsl:template name="user.head.content">
  <xsl:comment> (c) 2007 Copyright Megacorp, Inc. </xsl:comment>
  <base  target="{$target.window}"/>
</xsl:template>

If this document is processed with the custom parameter target.window set to 'main', then this customization adds this output to the HEAD:

<!-- (c) 2007 Copyright Megacorp, Inc. -->
<base target="main">

There is also a special empty placeholder template named user.preroot. This template is called before the html root element is output. Since it placed outside the root element, it cannot contain any elements or plain text. But the XML standard permits comments or processing instructions to be output before the root element. The most common processing instruction is the one that identifies a stylesheet to associate with the file.

Adding CSS style rules

Although you can specify a CSS stylesheet by using the html.stylesheet parameter, you may want to supplement it with additional CSS style rules in the head element. To do so, you can output an HTML style element using either the user.head.content template or the system.head.content template. The following example shows how to do it.

<xsl:template name="user.head.content">
  <style type="text/css">
    <xsl:comment>
      @import "stylesheets/override.css"
      body {background: url(graphics/bluesea.png);}
    </xsl:comment>
  </style>
</xsl:template>

This results in the following output in the HTML head element:

<style type="text/css">
  <!--
    @import "stylesheets/override.css"
    body {background: url(graphics/bluesea.png);}
  -->
</style>
 

Using the user.head.content template means these style rules will appear after the CSS stylesheet specified in html.stylesheet, so they will have higher CSS precedence. Using system.head.content instead means these style rules will appear before any other content in head, and so will have lower CSS precendence and can be overriden by rules in the file specified by html.stylesheet.

Embedding CSS styles

Instead of referring to an external CSS stylesheet, you may want to embed the CSS styles in your HTML output. That makes the HTML files more portable, since they no longer are dependent on a separate CSS file. You can make use of the placeholder template user.head.content as described in the following steps:

  1. Add a DOCTYPE declaration to your customization layer so you can declare a system entity that refererences your CSS stylesheet. For example:

    <?xml version="1.0"?>
    <!DOCTYPE xsl:stylesheet [
    <!ENTITY css SYSTEM "mystyle.css">
    ]>
    <xsl:stylesheet
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    

    A system entity is a way of identifying an external file. Adjust the path to the CSS file if it is not in the current directory. The path is taken to be relative to your customization file.

  2. Now you will use that system entity in the user.head.content in your customization:

    <xsl:template name="user.head.content">
    <style type="text/css">
    &css;
    </style>
    </xsl:template>
    

    This creates a style element in the HTML output and puts the content of the system entity into it. If the CSS file cannot be found or opened, the XSLT processor should report it as an error. do not forget to turn off the html.stylesheet parameter if you were using that to insert a reference the stylesheet.

Adding a date timestamp

You can add a date-of-processing timestamp in a META tag in your HTML HEAD output. This example uses an EXSLT extension function named date-time() that reads the system clock and generates a date timestamp at the moment the process is run. Not all XSLT processors support EXSLT functions, but Saxon, Xalan, and xsltproc do.

To add a date timestamp to your output, add a call to the extension function to the user.head.content template in your customization layer. You will also have to add a couple of attributes to the xsl:stylesheet element itself in order to identify the namespace used by the extension function. The following annotated example shows what needs to be done.

Example 12.1. Timestamp in meta element

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:date="http://exslt.org/dates-and-times"  1
                exclude-result-prefixes="date"  2
                version='1.0'>

<xsl:import href="../docbook-xsl-1.73.1/html/docbook.xsl"/>

<xsl:template name="user.head.content">  3
  <meta name="date">  4
    <xsl:attribute name="content">  5
      <xsl:call-template name="datetime.format">  6
        <xsl:with-param name="date" select="date:date-time()"/>  7
        <xsl:with-param name="format" select="'m/d/Y'"/>  8
      </xsl:call-template>
    </xsl:attribute>
  </meta>
</xsl:template>

...

1

You have to add the xmlns:date namespace declaration to the customization layer's xsl:stylesheet element.

2

Also add an exclude-result-prefixes attribute so the namespace does not appear in the HTML output.

3

The user.head.content template is an empty placeholder template in the stylesheets to be filled in by the customizer.

4

Start an HTML META element and give it a name="date" attribute.

5

Start the addition of a content attribute on the META element.

6

Call the stylesheet template datetime.format to generate the content attribute's value. That template is located in common/pi.xsl.

7

Pass the template a date parameter whose value is generated by the EXSLT date-time() function. The date: prefix ensures that this function call is not confused with the built-in XSLT functions.

8

Pass the template a format parameter whose value is a string of date and time component letters. The string must be enclosed in single quotes, or it will be misinterpreted as a document node resulting in a blank date output. These component letters are listed in the section “Date and time”. You can use whatever format you desire.


This example customization results in the following HTML output:

<meta name="date" content="03/10/2007">

This customization uses the datetime extension feature that is described in more detail in the section “Date and time”.

Removing the HEAD element

In some website setups, such as those that use Java ServerPages, HTML content is stored in modular pieces without HTML HEAD elements. The HTTP server is responsible for assembling a complete HTML file by dynamically adding a HEAD element. That makes it possible for the server to customize the output for each request. In other setups, the content files also have the HTML and BODY tags removed. Such content can be combined from several files by the server, which also dynamically adds the HTML, HEAD, and BODY tags.

If you want to generate such modular output, you will need to customize the template that generates the HTML wrapper elements. If you are using the nonchunking stylesheet, you want to customize the template with mode="process.root" in html/docbook.xsl. If you are using the chunking stylesheet, you need customize the chunk-element-content template in html/chunk-common.xsl.

In both cases, you want to eliminate all those parts of the template that output the HTML elements you do not want. If you want to eliminate just the HEAD, then remove the literal <head> and </head> tags and their content. If you want completely bare content, then remove the <html>, <head>, and <body> tags, as well as the template calls that fill the <head> element and generate the header and footer. There will not be much left. For example, process.root could end up looking like the following:

<xsl:template match="*" mode="process.root">
  <xsl:call-template name="root.messages"/>
  <xsl:apply-templates select="."/>
</xsl:template>