Inserting external HTML code

The server-side includes described in the previous section require you to configure an HTTP server to execute the includes when the file is accessed. What if you want to insert static HTML code from an external source into the HTML files that DocBook builds? For example, many website pages are based on templates that use boilerplate HTML code or Javascript libraries that already exist in external files. How do you insert such content verbatim into DocBook-generated HTML files?

The basic method is to use the XSLT document() function to open the code file, and then use xsl:copy-of to copy its content to your output. However, the document() function can only open well-formed XML files, not just any text file. But you can turn a text file into a well-formed XML document by wrapping its content in some element's start and end tags. Then the code text will be taken as the content of the wrapper element. As you will see in the examples below, you don't have to include the wrapper element in your output, so you can use any element name. The examples use htmlcode.

If your external code file includes HTML markup, be sure that any HTML elements are well-formed. The easiest way to do that is to convert it to XHTML. You can use the HTML Tidy tool to do that.

In the page header

If you want to insert the external code into the header on your HTML pages, you can use the user.header.content template as described in the section “HTML headers and footers”. Here is an example:

<xsl:template name="user.header.content">
   <xsl:variable name="codefile" select="document('mycode.html',/)"/>
   <xsl:copy-of select="$codefile/htmlcode/node()"/>
</xsl:template>

The first line of the template opens the code file and puts its well-formed content into a variable named codefile. This example assumes the code is contained in a file named mycode.html located in the current directory. You may want to make that a parameter reference so you can change the pathname more easily. You could also use a URI and have your XML catalog map that URI to the actual code file on your system. See Chapter 4, XML catalogs for more information about using catalogs.

The example also assumes the code file uses a wrapper element named htmlcode to make it well-formed XML. The second line of the template copies the content of the wrapper element to your output, without including the wrapper element itself. It selects using node(), which matches everything, including elements, text, comments, and processing instructions. If you don't want to hard code the wrapper element name in your template, then use this selection instead:

<xsl:copy-of select="$codefile/*/node()"/>

This will copy the content of whatever the root element is in the code file.

In the HEAD element

If you want to insert boilerplate HTML code into your HTML head element, then you can use the user.head.content template instead. See the section “HTML HEAD elements” for further information on that template. Here is an example that is similar to the one in the previous section:

<xsl:template name="user.head.content">
   <xsl:variable name="codefile" select="document('mycode.html',/)"/>
   <xsl:copy-of select="$codefile/htmlcode/node()"/>
</xsl:template>

In the page content

If you want to insert HTML code mixed in with the content of your pages, then you can use the same technique as the previous sections to customize any of the templates that generate output.

If you want the authors of your documents to be able to insert code in arbitrary places, then you can provide them with a processing instruction to indicate the location and filename. Here is how it is done.

  1. At the point where you want the HTML code inserted, add a processing instruction like this to your DocBook XML document:

    <?htmlcode  codefile13.html ?>
  2. If your external HTML code is not well-formed XML, then add a wrapper element around the whole file's contents. This means putting a start tag such as <mycode> at the beginning of the file and an end tag </mycode> at the end of the file. This ensures that the content is well-formed XML.

  3. Add the following template to your customization layer:

    <xsl:template match="processing-instruction('htmlcode')">
        <xsl:variable name="codefile" select="document(normalize-space(.),/)"/>
        <xsl:copy-of select="$codefile/*/node()"/>
      </xsl:template>
    

This example differs from the previous examples in two ways:

  • It uses a template that matches on any processing instruction whose name is htmlcode. You can assign any name to the PI.

  • It uses normalize-space(.) to get the value of the processing instruction (the dot), which is the code filename. The normalize-space() function converts the value to a string and trims off any leading or trailing white space from the filename.