<?xml version="1.0" encoding='ISO-8859-1'?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd">

<article id="docbook-autotools">
<artheader>
	<title>Using the GNU autotools with DocBook XML and <command>xsltproc</command></title>

	<authorgroup>
		<author>
			<firstname>John</firstname>
			<surname>Levon</surname>
			<affiliation>
				<address><email>levon@movementarian.org</email></address>
			</affiliation>
		</author>
	</authorgroup>

	<copyright>
		<year>2003</year>
		<holder>John Levon</holder>
	</copyright>

	<legalnotice>
	<para>This document can be freely translated and distributed. It's released
	under the LDP License.</para>
	</legalnotice>

	<keywordset>
		<keyword>DocBook</keyword>
		<keyword>XML</keyword>
		<keyword>autotools</keyword>
		<keyword>autoconf</keyword>
		<keyword>automake</keyword>
		<keyword>catalog</keyword>
		<keyword>XSLT</keyword>
		<keyword>xsltproc</keyword>
	</keywordset>
</artheader>

<chapter id="introduction"><title>Introduction</title> 
 
<para>
DocBook XML is a simple standard for authoring technical documentation. I wanted
to use DocBook XML as my source format for documentation for a project which
used the GNU autotools. It's less than obvious; this document describes the
method I used to get things working. It assumes that you are using the <command>xsltproc</command>
program to generate output from the source XML and a number of custom XSL stylesheets.
</para>
</chapter>

<chapter id="catalog"><title>Generating the XML catalog</title>

<para>
As of this document, the DocBook stylesheets cannot created "chunked" (that is, one document
split into several separate pages) XHTML output that passes the validators. In particular,
the files are missing a <computeroutput>!DOCTYPE</computeroutput> declaration. In addition,
I wanted to make some small modifications to the visual rendering.
</para>
<para>
The DocBook way to do this is to use custom stylesheets - these are essentially XSLT
source files that include the system's DocBook stylesheets, and add the necessary
modifications. The layout of the <filename>doc/</filename> directory containing
the DocBook source was as follows :
</para>
<programlisting> <!-- FIXME: bleh -->
	doc/
		Makefile.am
		source.xml
		xsl/
			xhtml.xsl
			xhtml-chunk.xsl
			xhtml-common.xsl
</programlisting>
<para>
Note that <filename>xhtml.xsl</filename> and <filename>xhtml-chunk.xsl</filename> both
include (<function>xsl:import</function>) <filename>xhtml-common.xsl</filename>.
This leaves us with two issues with respect to the GNU autotools: first, locating the
custom stylesheets, and second, locating the system stylesheets. We do both via
an XML catalog file. A catalog file is used for locating documents via URIs. To make
this work with <command>autoconf</command>, we make it an input file (that is, create
a file <filename>catalog.xml.in</filename> in the <filename>xsl/</filename> directory
and list it in <function>AC_OUTPUT</function> in <filename>configure.in</filename> as
usual). Our <filename>doc/xsl/catalog.xml.in</filename> looks like this :
</para>
<programlisting>
&lt;?xml version="1.0"?&gt;
&lt;!DOCTYPE catalog PUBLIC "-//OASIS/DTD Entity Resolution XML Catalog V1.0//EN"
        "http://www.oasis-open.org/committees/entity/release/1.0/catalog.dtd"&gt;

&lt;catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog"&gt;
        &lt;nextCatalog catalog="@XML_CATALOG@" /&gt;

        @CAT_ENTRY_START@
        &lt;uri name="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"
                uri="@DOCBOOK_ROOT@/xhtml/docbook.xsl"/&gt;
        &lt;uri name="http://docbook.sourceforge.net/release/xsl/current/xhtml/chunk.xsl"
                uri="@DOCBOOK_ROOT@/xhtml/chunk.xsl"/&gt;
        @CAT_ENTRY_END@

        &lt;uri name="xsl/xhtml-common.xsl" uri="@top_srcdir@/doc/xsl/xhtml-common.xsl"/&gt;
&lt;/catalog&gt;
</programlisting>
<para>
There are three things to note here. First, that we try and find the system's XML catalog,
which, if it exists, should contain the local file URIs for the DocBook stylesheets; this
means that, when we refer to the <filename>docbook.xsl</filename> URI, we will get the local
file version instead of going over the net to request it. This <function>nextCatalog</function>
declaration silently fails if the file does not exist, so that's OK.
</para>
<para>
Second, we have explicit declarations for the two DocBook stylesheets I want to use.
<varname>@DOCBOOK_ROOT@</varname> is the directory location of the XSL stylesheets,
if we could find them. If the catalog file was found, then this section is commented
out via the <varname>CAT_ENTRY</varname> being set to XML comment delimiters - we do
not want to over-ride a value set in a system catalog.
</para>
<para>
Finally, we have a catalog entry for the custom <filename>xhtml-common.xsl</filename> stylesheet,
which is included by the others as mentioned above. This is necessary to build correctly
when building in a different directory than the source directory - the <filename>.xsl</filename>
files will be in the <filename>${top_srcdir}/doc/xsl/</filename>, but the current directory
will not be <filename>$top_srcdir}/doc</filename>.
</para>
</chapter>

<chapter id="configure"><title>Creating a DocBook <command>autoconf</command> macro</title>
<para>
We need to derive the variables mentioned in the last chapter, plus a couple more. Here
is an example macro for this :
</para>
<programlisting>
AC_DEFUN(AX_CHECK_DOCBOOK, [
# It's just rude to go over the net to build
XSLTPROC_FLAGS=--nonet
DOCBOOK_ROOT=
if test ! -f /etc/xml/catalog; then
        for i in /usr/share/sgml/docbook/stylesheet/xsl/nwalsh /usr/share/sgml/docbook/xsl-stylesheets/;
        do
                if test -d "$i"; then
                        DOCBOOK_ROOT=$i
                fi
        done

        # Last resort - try net
        if test -z "$DOCBOOK_ROOT"; then
                XSLTPROC_FLAGS=
        fi
else
        XML_CATALOG=/etc/xml/catalog
        CAT_ENTRY_START='&lt;!--'
        CAT_ENTRY_END='--&gt;'
fi

AC_CHECK_PROG(XSLTPROC,xsltproc,xsltproc,)
XSLTPROC_WORKS=no
if test -n "$XSLTPROC"; then
        AC_MSG_CHECKING([whether xsltproc works])

        if test -n "$XML_CATALOG"; then
                DB_FILE="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"
        else
                DB_FILE="$DOCBOOK_ROOT/docbook.xsl"
        fi

        $XSLTPROC $XSLTPROC_FLAGS $DB_FILE &gt;/dev/null 2&amp;&gt;&amp;1 &lt;&lt; END
&lt;?xml version="1.0" encoding='ISO-8859-1'?&gt;
&lt;!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN" "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"&gt;
&lt;book id="test"&gt;
&lt;/book&gt;
END
        if test "$?" = 0; then
                XSLTPROC_WORKS=yes
        fi
        AC_MSG_RESULT($XSLTPROC_WORKS)
fi
AM_CONDITIONAL(have_xsltproc, test "$XSLTPROC_WORKS" = "yes")

AC_SUBST(XML_CATALOG)
AC_SUBST(XSLTPROC_FLAGS)
AC_SUBST(DOCBOOK_ROOT)
AC_SUBST(CAT_ENTRY_START)
AC_SUBST(CAT_ENTRY_END)

</programlisting>
<para>
We define the variables we mentioned in the previous chapter. Additionally
we set <varname>@XSLTPROC_FLAGS@</varname> so that we only retrieve stylesheets
over the network as a last resort. Note that this test does not check that
a system that has an <filename>/etc/catalog/xml</filename> file works as expected.
You may need or want to change the DocBook root directories that are searched for.
</para>
<para>
The only other <filename>configure.in</filename> change you need is to add
<filename>doc/xsl/catalog.xml</filename> to the <function>AC_OUTPUT</function> files.
</para>
</chapter>

<chapter id="makefile"><title>A suitable <filename>Makefile.am</filename></title>
<para>
Here is a suitable cut-down <command>automake</command> input file for the setup
above :
</para>
<programlisting>
XSLTPROC=xsltproc
XSLTPROC_FLAGS=@XSLTPROC_FLAGS@
XHTML_STYLESHEET=$(srcdir)/xsl/xhtml.xsl
CHUNK_XHTML_STYLESHEET=$(srcdir)/xsl/xhtml-chunk.xsl
XML_CATALOG_FILES=xsl/catalog.xml

htmldir = $(prefix)/share/doc/@PACKAGE@
dist_html_DATA = @PACKAGE@.html

if have_xsltproc

@PACKAGE@.html: ${top_srcdir}/doc/@PACKAGE@.xml
        XML_CATALOG_FILES=$(XML_CATALOG_FILES) $(XSLTPROC) $(XSLTPROC_FLAGS) -o $@ $(XHTML_STYLESHEET) $&lt;

chunk: ${top_srcdir}/doc/@PACKAGE@.xml
        $(XSLTPROC) $(XSLTPROC_FLAGS) $(CHUNK_XHTML_STYLESHEET) $&lt;

else

chunk:

@PACKAGE@.html:
        touch $@

endif

distclean-local:
        $(RM) -f xsl/catalog.xml
</programlisting>
<para>
Clearly not the greatest Makefile ever, but you get the idea. The <command>chunk</command>
target generates the chapter-per-file XHTML output. Note that we use <varname>XML_CATALOG_FILES</varname>
in the environment to specify the catalog file to <command>xsltproc</command>. Later
<command>xsltproc</command> versions allow you to specify more than one catalog
in this variable, separated by spaces; but as it's not universal, we've used
<function>nextCatalog</function> instead.
</para>
</chapter>

<chapter id="stylesheet"><title>The custom stylesheet</title>
<para>
Here's a listing of the simpler custom style sheet. Note that
the system DocBook stylesheet is referred to by the URI given
in the catalog files, and the common custom stylesheet is referred to
directly.
</para>
<programlisting>
&lt;?xml version='1.0'?&gt;
&lt;xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
	xmlns:doc="http://nwalsh.com/xsl/documentation/1.0" version="1.0"&gt;

&lt;xsl:import href="http://docbook.sourceforge.net/release/xsl/current/xhtml/docbook.xsl"/&gt;
&lt;xsl:import href="xhtml-common.xsl"/&gt;

&lt;xsl:output method="xml" encoding="ISO-8859-1" indent="yes"
	doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN"
	doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd" /&gt;

&lt;/xsl:stylesheet>
</programlisting>
</chapter>
<chapter id="references"><title>References</title>
<para>
Much thanks to Alex Lancaster who helped explain some of this to me.
</para>
<variablelist>
<varlistentry>
	<term><ulink url="http://lists.oasis-open.org/archives/docbook-apps/200303/msg00076.html" /></term>
	<listitem>
	A thread on the docbook-apps mailing list discussing the above problems.
	</listitem>
</varlistentry>
<varlistentry>
	<term><ulink url="http://www.sagehill.net/xml/docbookxsl/Catalogs.html" /></term>
	<listitem>
	A description of using XML catalogs for finding stylesheets.
	</listitem>
</varlistentry>
<varlistentry>
	<term><ulink url="http://sources.redhat.com/autobook/" /></term>
	<listitem>
	A free book on the GNU Autotools.
	</listitem>
</varlistentry>
<varlistentry>
	<term><ulink url="http://www.docbook.org/tdg/en/html/docbook.html" /></term>
	<listitem>
	A free book on DocBook SGML/XML.
	</listitem>
</varlistentry>
</variablelist>

</chapter>


</article>
