Menu

DocBook for Eclipse: Reusing DocBook's Stylesheets

August 13, 2003

Jirka Kosek

DocBook is a popular tool for creating software documentation among developers. One reason for its success is the existence of the DocBook XSL stylesheets, which can be used to convert DocBook XML source into many target formats including HTML, XHTML, XSL-FO (for print), JavaHelp, HTML Help, and man pages. The stylesheets can be further customized to get other outputs as well. In this article I am going to show you how easily you can integrate DocBook documents into the Eclipse platform help system by reusing existing stylesheets.

Many help systems currently in use are built around HTML. The best known is probably Microsoft's HTML Help, dominant on the Windows platform. (You can easily find the HTML Help files on your Windows system: their suffix is .chm.) The corresponding technology in the Java world is JavaHelp, and there are many other formats besides. All of them share one common characteristic -- they are just a set of HTML files supplemented by auxiliary files containing the table of contents and other additional metadata.

These auxiliary files are usually XML or HTML-based, so we can use XSLT to generate them. If you have your documentation in DocBook and you want to feed it into the help system, the only thing you need is to extend the existing stylesheets to emit the auxiliary files together with a standard HTML output. That is even easier if you reuse some existing DocBook XSL stylesheet templates.

Inside Eclipse platform help

The whole Eclipse platform is developed around the idea of plugins. If you want to contribute your help documents to the Eclipse platform, you have to develop a new help plugin. The plugin is composed of the HTML and image files, the table of contents file in XML, and the manifest file.

The table of contents file describes the nested structure of topics which is displayed in the left pane of the help system. The manifest file (plugin.xml) is used for registering a new plugin inside the Eclipse platform.

The table of contents file is a simple tree-structured XML file containing the names of all topics and their subtopics, together with the filenames of corresponding HTML pages with help content. You can see sample table of contents file on Figure 1:

Screen shot of table of contents and XML structure which describes it.
Figure 1. Table of contents and XML structure which describes it.

The manifest file is not very interesting, but the Eclipse platform needs it for recognizing the plugin and adding it into the global table of contents:

<?xml version="1.0" encoding="utf-8"?>
<plugin name="DocBook Online Help Sample" 
        id="com.example.help" 
        version="1.0" 
        provider-name="Example provider">
   <extension point="org.eclipse.help.toc">
      <toc file="toc.xml" primary="true"/>
   </extension>
</plugin>

If you want to use your own help inside the Eclipse platform, you must create a new directory inside the plugins directory named the same as the content of id attribute (com.example.help in our example). The manifest file, the table of contents file, and all HTML files must be placed inside this directory. After restarting the Eclipse platform our help will be part of the Eclipse help, and a new item it will be displayed in the global table of contents.

Extending DocBook XSL stylesheets

As the Eclipse help is based on HTML, we can reuse existing stylesheets that generate multiple HTML files from DocBook XML source. However, we need to extend these stylesheets to generate the table of contents file and the manifest file.

The first thing that has to be done when reusing an existing stylesheet is to import it. The first XSLT instruction in our stylesheet thus has to be

<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/>

Of course you can change the URL of the stylesheet to point to your local copy of the DocBook XSL stylesheet or better you can use catalog files for doing such resource redirection.

Next we must invoke the original stylesheet code to get HTML files from the XML source and then invoke our code to generate the table of contents and manifest files.

<xsl:template match="/">
  <!-- Call original code from the imported stylesheet -->
  <xsl:apply-imports/>

  <!-- Call custom templates for the ToC and the manifest -->
  <xsl:call-template name="etoc"/>
  <xsl:call-template name="plugin.xml"/>
</xsl:template>

We start with the second template, which generates the manifest file, as it is very simple and demonstrates a cool template which is a part of the DocBook XSL stylesheets.

The plugin.xml template must generate a simple manifest file and save it into the plugin.xml file. Generating multiple output files with XSLT is not standardized in XSLT 1.0, and each XSLT processor utilizes its own extension instruction to do it (many of processors also support EXSLT instruction for doing this). To isolate the stylesheet developer from processor differences, the DocBook XSLT stylesheets define a write.chunk template which will select and use appropriate processor-dependent instruction for you. By using parameters you can feed the template with important information like the name of the generated file or its content.

<xsl:template name="plugin.xml">
  <xsl:call-template name="write.chunk">
    <xsl:with-param name="filename" select="'plugin.xml'"/>
    <xsl:with-param name="method" select="'xml'"/>
    <xsl:with-param name="encoding" select="'utf-8'"/>
    <xsl:with-param name="indent" select="'yes'"/>
    <xsl:with-param name="content">
      <plugin name="{$eclipse.plugin.name}"
              id="{$eclipse.plugin.id}"
              version="1.0"
              provider-name="{$eclipse.plugin.provider}">
        <extension point="org.eclipse.help.toc">
          <toc file="toc.xml" primary="true"/>
        </extension>
      </plugin>
    </xsl:with-param>
  </xsl:call-template>
</xsl:template>

As you can see, the global parameters are used to allow the stylesheet user to easily customize things like plugin name or id.

The most important part of the stylesheet is the etoc template, responsible for generating the the table of contents file for the Eclipse platform help system. We will use write.chunk template introduced before to create a separate toc.xml file. The table of contents file must contain the hierarchy of the topic elements which corresponds to structure of our document. This can be generated very easily using XSLT. You must create a template which will process all DocBook container elements like chapter, appendix, and section; for each such element it will add the corresponding topic element to the output.

Each topic should be provided with its name and name of the HTML file which holds its contents. The DocBook XSLT stylesheets already contain code for getting this information. If you apply templates in title.markup mode to some node, you will get its title. Similarly you can use the named template href.target.with.base.dir to get the filename which contains output of specific node in your source DocBook document.

If you combine all the templates together you will get this, still quite simple, stylesheet with which you can turn any valid DocBook instance into Eclipse platform help.

<?xml version="1.0"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

<!-- Import of the original stylesheet which "just" creates 
     a bunch of HTML files from any valid DocBook instance -->
<xsl:import href="http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl"/>

<!-- You must plug-in your custom templates here --> 
<xsl:template match="/">
  <!-- Call original code from the imported stylesheet -->
  <xsl:apply-imports/>

  <!-- Call custom templates for the ToC and the manifest -->
  <xsl:call-template name="etoc"/>
  <xsl:call-template name="plugin.xml"/>
</xsl:template>

<!-- Template for creating auxiliary ToC file -->
<xsl:template name="etoc">
  <xsl:call-template name="write.chunk">
    <xsl:with-param name="filename" select="'toc.xml'"/>
    <xsl:with-param name="method" select="'xml'"/>
    <xsl:with-param name="encoding" select="'utf-8'"/>
    <xsl:with-param name="indent" select="'yes'"/>
    <xsl:with-param name="content">

      <!-- Get the title of the root element -->
      <xsl:variable name="title">
        <xsl:apply-templates select="/*" mode="title.markup"/>
      </xsl:variable>
    
      <!-- Get HTML filename for the root element -->
      <xsl:variable name="href">
        <xsl:call-template name="href.target.with.base.dir">
          <xsl:with-param name="object" select="/*"/>
        </xsl:call-template>
      </xsl:variable>
      
      <!-- Create root element of ToC file -->
      <toc label="{$title}" topic="{$href}">
        <!-- Get ToC for all children of the root element -->
        <xsl:apply-templates select="/*/*" mode="etoc"/>
      </toc>
      
    </xsl:with-param>
  </xsl:call-template>
</xsl:template>

<!-- Template which converts all DocBook containers into 
     one entry in the ToC file -->
<xsl:template match="book|part|reference|preface|chapter|
                     bibliography|appendix|article|glossary|
                     section|sect1|sect2|sect3|sect4|sect5|
                     refentry|colophon|bibliodiv|index" 
              mode="etoc">
  <!-- Get the title of the current element -->
  <xsl:variable name="title">
    <xsl:apply-templates select="." mode="title.markup"/>
  </xsl:variable>

  <!-- Get HTML filename for the current element -->
  <xsl:variable name="href">
    <xsl:call-template name="href.target.with.base.dir"/>
  </xsl:variable>

  <!-- Create ToC entry for the current node and process its 
       container-type children further -->
  <topic label="{$title}" href="{$href}">
    <xsl:apply-templates select="part|reference|preface|chapter|
                                 bibliography|appendix|article|
                                 glossary|section|sect1|sect2|
                                 sect3|sect4|sect5|refentry|
                                 colophon|bibliodiv|index" 
                         mode="etoc"/>
  </topic>

</xsl:template>

<!-- Default processing in the etoc mode is no processing -->
<xsl:template match="text()" mode="etoc"/>

<!-- Template for generating the manifest file -->
<xsl:template name="plugin.xml">
  <xsl:call-template name="write.chunk">
    <xsl:with-param name="filename" select="'plugin.xml'"/>
    <xsl:with-param name="method" select="'xml'"/>
    <xsl:with-param name="encoding" select="'utf-8'"/>
    <xsl:with-param name="indent" select="'yes'"/>
    <xsl:with-param name="content">
      <plugin name="{$eclipse.plugin.name}"
              id="{$eclipse.plugin.id}"
              version="1.0"
              provider-name="{$eclipse.plugin.provider}">
        <extension point="org.eclipse.help.toc">
          <toc file="toc.xml" primary="true"/>
        </extension>
      </plugin>
    </xsl:with-param>
  </xsl:call-template>
</xsl:template>

<!-- Customization parameters for the manifest file -->
<xsl:param name="eclipse.plugin.name">DocBook Online Help Sample</xsl:param>
<xsl:param name="eclipse.plugin.id">com.example.help</xsl:param>
<xsl:param name="eclipse.plugin.provider">Example provider</xsl:param>

</xsl:stylesheet>

More customizations

Now that you have working solution for transforming DocBook to Eclipse platform help, you can start fiddling with the appearance of the output. There are a lot of documented parameters which control the presentation and shape of the HTML output. It's common to create a custom CSS stylesheet for changing the presentation of the generated HTML and to set parameters in such a way that generated topics are as small as possible. You can achieve this by adding following parameters into your stylesheet:

<xsl:param name="html.stylesheet">eclipse.css</xsl:param>
<xsl:param name="chunk.first.sections" select="1"/>
<xsl:param name="chunk.section.depth" select="3"/>

Many other useful tips for customizing the DocBook XSLT stylesheets are described in the book DocBook XSL: The Complete Guide from Bob Stayton.

Screen shot of large DocBook document displayed inside the Eclipse help system.
Figure 2. Large DocBook document displayed inside the Eclipse help system.

Conclusion

Software documentation is an area where you can very effectively use XML and XSLT to do multichannel publishing. If you stick to using a well-known and standardized vocabulary like DocBook, you can benefit from usage of existing stylesheets and other conversion tools. If you want to plug your DocBook documentation into some new help format, you can quite easily hack existing stylesheets to generate a new output format. The method for creating output for the Eclipse platform help described in this article can be used for almost any HTML based online help system.

Related links