General Styling Questions

1. Which stylesheets do what?
2. How to use a CSS stylesheet with docbook
3. Produce html and pdf via fop.
4. Changing the output encoding for website
5. literallayout and programlisting
6. Using Namespace in XSL to generate XSL from Docbook
7. Grouping Glossary entries.
8. Image sizing
9. Styling html output
10. Implementing Cals Tables
11. Graphic file format in XSL stylesheets
12. No en localization errors
13. Breaking long strings such as url's
14. Using changebars and chunk.xsl together
15. Does stylesheet processing validate the source document?
16. The Unicode Bidirectional Algorithm
17. Seperating footnotes from body text
18. XHTML table output
19. Insert date into output
20. Admonition styling
21. CSS styling on tables
22. Including SVG in docbook
23. Segmented list decoration
24. Processing docbook, catalogs, Xinclude and XSLT processor
25. Localisation in seperate files
26. Docbook to text. Method 1.
27. Table of Content

1.

Which stylesheets do what?

Jirka Kosek

Now there are only two stylsheets for HTML: docbook.xsl and chunk.xsl. Autoindexing is now integral part of both of them, there is no need to use separate autoidx.xsl as in older releases. onechunk.xsl is just abnormality which was added upon request for some user, and it looks like that this stylesheets is broken now.

Output format: stylesheet to use
Single HTML:html/docbook.xsl
Chunked HTML: html/chunk.xsl
Single XHTML: xhtml/docbook.xsl
Chunked XHTML:xhtml/chunk.xsl
FO:fo/docbook.xsl
HTML Help:htmlhelp/htmlhelp.xsl
Java Help:javahelp/javahelp.xsl

These files are main entry points of DocBook XSL stylesheets. Normal user doesn't need to directly call any other stylesheet. I hope that I listed all top-level stylesheets.

2.

How to use a CSS stylesheet with docbook

Bob Stayton




> So ... after I've run db2html on my *.sgml files, Am I supposed to edit the
> outputted html to include CSS style sheets? If so, that's alot of work to
> throw away everytime I re-run db2html. 

No need to edit the output files. You can create a separate CSS stylesheet file that contains all the style information, and then associate that stylesheet with all of your html files. If you look at the HTML output from DocBook, you'll see a lot of <div class="element"> tags, where "element" is the DocBook element that produced that <div>. You write your css stylesheet to associate CSS styles with those div class tags (see a good css a reference to learn how to do that).

To connect it with your files, you set the 'html.stylesheet' parameter in either DSSSL or XSL to the name of your stylesheet file. You do that in a stylesheet customization, which is described inthe faq. That parameter causes an HTML element to be inserted into each generated HTML file that associates your css stylesheet with that HTML file. Then just make sure the stylesheet file gets copied to each HTML output directory. It's a nice system because you can control all the formatting for all of your output from a single css file.

3.

Produce html and pdf via fop.

Brendan Boyle

Here is a *nix script to produce both html and pdf using fop.




#!/bin/bash

# - xmlconv
# Brendan Boyle Shadowtech Pty Ltd
# brendan@shadowtech.com.au
# Simple xml converter script
#
# HTML:
# Outputs a single html file, multiple html files using xtchunk.xsl and a pdf file 
#
# PDF:
# Outputs a fop file and creates a pdf based on the fop file 
#
# Takes  one parameter: File Name to be converted
#
# Usage: xmlconv <filename>
#
# Assumptions:
# A working installation of java
# xt, xp, Fop and docbook are each stored under /usr/local
# Each of these programs can be located at the following locations
# xt: http://www.jclark.com/xml/
# xp: http://www.jclark.com/xml/
# Fop: http://xml.apache.org/fop/download.html
# docbook: http://sourceforge.net/projects/docbook/ (download docbook-xsl)
# java: http://java.sun.com/ or http://www.blackdown.org/
#

# Modify the options below if your files are stored elsewhere
# Location of class files (used when exporting CLASSPATH variable later)
CLASSFILES="/usr/local/xt/xt.jar:/usr/local/xp/xp.jar:/usr/local/xt/sax.jar"
# Location of docbook xsl file
XSLLOCATION="/usr/local/docbook/html/docbook.xsl"
FOPXSL="/usr/local/docbook/fo/docbook.xsl"
CHUNKLOCATION="/usr/local/docbook/html/xtchunknew.xsl"
FOPLOCATION="/usr/local/Fop"


if [ $# -ne 1 ]
then
echo "Incorrect number of parameters."
echo "Usage: xmlconv <filename>"
exit -1
fi

# Check for files existence
if [ ! -f $1 ]
then
echo "The selected file does not exist.  Please type the name of a real file"
exit -1
fi

# Remove the xml extension from the file
FILENAME=`dirname $1`"/"`basename $1 .xml`


# Perform conversion to single html file
echo "Creating $FILENAME.html..."
export CLASSPATH=$CLASSFILES
java com.jclark.xsl.sax.Driver $FILENAME.xml $XSLLOCATION > $FILENAME.html
#java com.icl.saxon.StyleSheet $FILENAME.xml  $XSLLOCATION > $FILENAME.html


# Perform conversion to multiple html files
echo "Converting $FILENAME.xml to multiple html pages..."
java com.jclark.xsl.sax.Driver $FILENAME.xml $CHUNKLOCATION


# Perform conversion to fop file
echo "Creating fop file..."
java com.jclark.xsl.sax.Driver $FILENAME.xml $FOPXSL > $FILENAME.fop


# Perform conversion from fop to pdf
echo "Creating pdf file..."
CLASSFILES="/usr/local/Fop/build/fop.jar:/usr/local/Fop/lib/batik.jar:/usr/local/Fop/lib/xalan-2.0.0.jar:/usr/local/Fop/lib/xerces-1.2.3.jar:/usr/local/Fop/lib/jimi-1.0.jar"
export CLASSPATH=$CLASSFILES
java org.apache.fop.apps.Fop $FILENAME.fop -pdf $FILENAME.pdf


4.

Changing the output encoding for website

Jirka Kosek


> I use Website version 2.0a2a1 for my homesite. The pages are written in
> slovak language with latin-2 encoding. As XSLT I use saxon 6.2.2 with
> crimson as parser for XML and XSL files.

> My questions are: how can I determinate output encoding by transformation
> and how should I set the encoding in the head of html file.

At first, you should upgrade at least to Saxon 6.4.3. Previous version contained some serious bugs making DocBook chunking unusable.

It depends on website usage. If you generete website using Makefile and make program, you must create customization stylesheet like this:

<?xml version="1.0" encoding="iso-8859-2"?> <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0" xmlns:saxon="http://icl.com/saxon" extension-element-prefixes="saxon"> <xsl:import href="file:///path/to/website/xsl/tabular.xsl"/> <xsl:output method="html" encoding="iso-8859-2" saxon:character-representation="native"/> </xsl:stylesheet>

Now use this stylesheet instead of supplied one.

If you are not using makefiles and dependency checking and multiple file generation is left to XSLT extensions, you should create following customization:

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

<xsl:import href="file:///path/to/website/xsl/chunk-tabular.xsl"/>

<xsl:param name="default.encoding">iso-8859-2</xsl:param>
<xsl:param name="saxon.character.representation">native</xsl:param>

</xsl:stylesheet>

Output encoding in meta tag of generated HTML files is inserted automatically by XSLT processor. This encoding can be changed by mechanism described above.

5.

literallayout and programlisting

Eric Richardson

Here is what I found about <programlisting> and <literallayout>.

1. If the markup includes only text inside of <programlisting> or <literallayout class="monospaced"> then all whitespace is significant. This is expected as these translate directly to <pre class="xxx">. This includes <filename> inside <programlisting> as this translates to <tt>.

2. If the elements have a <inlinemediaobject> inside so you can use <imageobject> and then <imagedata fileref="sometext" format="linespecific"> so you can enable extensions to include the external file then things change a bit. Only the space between the programlisting|literallayout and <inlinemediaobject> seem to be relevent.

There are three ways it works okay from my perspective.

1. If there is no space between the elements then it works but the source looks ugly.

2. If you put the <inlinemediaobject> on the next line, left justified. This looks better and doesn't seem to effect the output. The <span class="inlinemediaobject> is put on the next line after the <pre>.

3. Leave an extra empty line in the file. This makes extra space in the result and is really undesirable.

I really don't understand the stylesheets well enough to play around for different approaches but I feel this is a bit confusing. Most people understand the idea of literal text like <pre> but the interaction with included text is really non-intuitive based on the fact that markup isn't suppose to matter that much in source form and indenting seems the most comfortable. Also postprocessors are a factor as well but they should not mess with the content of a <pre> either way.

6.

Using Namespace in XSL to generate XSL from Docbook

Norm Walsh





|  Bob> You need to make a couple of changes to get the namespace into
|  Bob> the attribute name.  First, you need to declare the namespace
|  Bob> and prefix in your stylesheet:
|
|  Bob> <xsl:stylesheet 
|  Bok>     xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
|  Bob>     xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0">
|
| That leaves me with the top level element
| <book xmlns:xlink="http://www.w3.org/1999/xlink">, where the
| xmlns:xlink attribute  is not declared in the DTD.  

If you want to limit the namespace declarations in the output, put the xmlns: on the xsl:template that processes xrefs, not at the top level:

 <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
 ...
 <xsl:template match="xref" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0">
   match on xlink:type etc, whatever you want
 </xsl:template>
 ...
 </xsl:stylesheet>

That usually limits the placement of namespace decls in the output to appropriate places.

Note, however, that the XSLT Rec requires only that processors output sufficient namespace declarations to form a legal XML+Namespaces document.

7.

Grouping Glossary entries.

Mike Smith


> Is there anyone who has experience in selecting particular GlossEntries
> for processing?

> My plan is to create one big Glossary that contains GlossEntries related
> to different products (for
> company internal usage).
> As part of the product documentation, I want to create product-related
> glossaries.
> Can anyone give me advice how I can proceed?

Off the shelf, DocBook provides a "subject" attribute on Glossdef, so you could use that to associate each of Glossdef with a product. But... it seems like what would be more useful is a flag on each Glossentry container instead, so maybe something like this:

    <glossentry id="gloss.foo" role="product_one">
      <glossterm>foo</glossterm>
      <glossdef>
        <para>A widget used in Product One.</para>
      </glossdef>
    </glossentry>

That way, you could then use Jirka Kosek's profiling stylesheet in the XSLT stylesheet distribution (tools/profile/profile.xsl) to generate product-specific versions of the glossary. Just set the value of the XSLT "attr" parameter to "role" and the value of the "val" parameter to the product categories you want; for example, using Saxon, to generate a glossary containing just entries you've flagged with "product_one" and "product_three", you'd do something like this:

  java com.icl.saxon.StyleSheet \
    glossary.xml /docbook-xsl/tools/profile/profile.xsl \
    attr=role val=product_one;product_three

And to make things easier on yourself, I think you could save the trouble of typing your product names each time if you worked from a DTD customization layer in which you set the value of the "role" attribute for Glossentry to an enumerated list of your product categories, which you could do by redefining the glossentry.role.attrib parameter entity like this:

<!ENTITY % glossentry.role.attrib
           "role    (product_one
                     | product_two
                     | product_three) #IMPLIED">

8.

Image sizing

Michael Smith

I think it breaks down like this. Imagine that "image.eps" is 6in wide and 10in deep.

<imagedata 
fileref="image.eps" 
width="3in" depth="5in" 
scalefit="1"/>

Renders the image at a size of 3in by 5in. (I think specifying only the width or depth should have the same effect; specifying width="3in" depth="3in" should scale the figure anamorphically.)

<imagedata 
fileref="image.eps"
 width="3in" depth="5in"/>

Renders the 6in x 10in image in a 3in x 5in space (we don't have an attribute to control whether the image would be cropped or overprinted, so you'd get whatever the stylesheets say).

<imagedata 
fileref="image.eps" 
scale="120%">

Renders a 7.2in x 12in image.

<imagedata 
fileref="image.eps" 
width="100%" 
scalefit="1"/>

Renders an image scaled to a width (with properly scaled depth) of 100% of the available area. (What constitutes the available area depends on the context, of course. In print, it would usually be the column width.)

<imagedata fileref="image.eps" width="100%"/>

Renders the 6in x 10in image in space equal to the width of the available area. (we don't have an attribute to control whether the image would be cropped or overprinted, so you'd get whatever the stylesheets say).

9.

Styling html output

Bob Stayton


> Is it possible to properly mark up source code in a docbook file so that
> meinproc will produce html with the source code in a 'greybar' or colored
> background?

This is most easily done with a CSS stylesheet associated with your HTML output. You can do that with the 'html.stylesheet' parameter. If you look in the generated HTML output, you'll see each element is output in a <div class="elementname">, which makes writing css stylesheets that style specific elements easy. If you put your source code in <programlisting> elements, and create a CSS stylesheet that styles div.programlisting, then you can get what you want.

10.

Implementing Cals Tables

Andrew Welch

For anybody thats interested, this in an implementation of Norman Walsh's docbook tables that handles <spanspec> (using some code from David McNally).

I have stripped out as much non-essential code as possible, so if anyone needs to add functionality they shouldnt have too much trouble following the code (well, less trouble than I had ;)

If anybody adds to this to make it closer to the CALS spec, please let me know so I can update mine.


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

<xsl:param name="default.table.width" select="'80%'"/>

<xsl:template match="tgroup">
  <table>
    <xsl:if test="../@pgwide=1">
      <xsl:attribute name="width">100%</xsl:attribute>
    </xsl:if>

    <xsl:if test="@align">
      <xsl:attribute name="align">
        <xsl:value-of select="@align"/>
      </xsl:attribute>
    </xsl:if>

    <xsl:choose>
      <xsl:when test="../@frame='TOPBOT'">
        <xsl:attribute 
  name="style">border-top:thin solid
  black;border-bottom:thin solid black</xsl:attribute>
      </xsl:when>
      <xsl:otherwise>
        <xsl:attribute name="border">0</xsl:attribute>
      </xsl:otherwise>
    </xsl:choose>

    <xsl:variable name="colgroup">
      <colgroup>
        <xsl:call-template name="generate.colgroup">
          <xsl:with-param name="cols" select="@cols"/>
        </xsl:call-template>
      </colgroup>
    </xsl:variable>

    <xsl:variable name="table.width">
      <xsl:choose>
        <xsl:when test="$default.table.width = ''">
          <xsl:text>100%</xsl:text>
        </xsl:when>
        <xsl:otherwise>
          <xsl:value-of select="$default.table.width"/>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:attribute name="width">
       <xsl:value-of select="$table.width"/>
    </xsl:attribute>


    <xsl:copy-of select="$colgroup"/>

    <xsl:apply-templates/>

   </table>
</xsl:template>

<xsl:template match="colspec"></xsl:template>

<xsl:template match="spanspec"></xsl:template>

<xsl:template match="thead|tfoot">
  <xsl:element name="{name(.)}">
    <xsl:if test="@align">
      <xsl:attribute name="align">
        <xsl:value-of select="@align"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@char">
      <xsl:attribute name="char">
        <xsl:value-of select="@char"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@charoff">
      <xsl:attribute name="charoff">
        <xsl:value-of select="@charoff"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@valign">
      <xsl:attribute name="valign">
        <xsl:value-of select="@valign"/>
      </xsl:attribute>
    </xsl:if>

    <xsl:apply-templates/>
  </xsl:element>
</xsl:template>

<xsl:template match="tbody">
  <tbody>
    <xsl:if test="@align">
      <xsl:attribute name="align">
        <xsl:value-of select="@align"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@char">
      <xsl:attribute name="char">
        <xsl:value-of select="@char"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@charoff">
      <xsl:attribute name="charoff">
        <xsl:value-of select="@charoff"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@valign">
      <xsl:attribute name="valign">
        <xsl:value-of select="@valign"/>
      </xsl:attribute>
    </xsl:if>

    <xsl:apply-templates/>
  </tbody>
</xsl:template>

<xsl:template match="row">
  <tr>
    <xsl:if test="@align">
      <xsl:attribute name="align">
        <xsl:value-of select="@align"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@char">
      <xsl:attribute name="char">
        <xsl:value-of select="@char"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@charoff">
      <xsl:attribute name="charoff">
        <xsl:value-of select="@charoff"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@valign">
      <xsl:attribute name="valign">
        <xsl:value-of select="@valign"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:apply-templates/>
  </tr>
</xsl:template>

<xsl:template match="thead/row/entry">
  <xsl:call-template name="process.cell">
    <xsl:with-param name="cellgi">th</xsl:with-param>
  </xsl:call-template>
</xsl:template>

<xsl:template match="tbody/row/entry">
  <xsl:call-template name="process.cell">
    <xsl:with-param name="cellgi">td</xsl:with-param>
  </xsl:call-template>
</xsl:template>

<xsl:template match="tfoot/row/entry">
  <xsl:call-template name="process.cell">
    <xsl:with-param name="cellgi">th</xsl:with-param>
  </xsl:call-template>
</xsl:template>

<xsl:template name="process.cell">
  <xsl:param name="cellgi">td</xsl:param>


  <xsl:variable name="empty.cell" select="count(node()) = 0"/>

  <xsl:variable name="entry.colnum">
    <xsl:call-template name="entry.colnum"/>
  </xsl:variable>

  <xsl:if test="$entry.colnum != ''">
    <xsl:variable name="prev.entry" select="preceding-sibling::*[1]"/>
    <xsl:variable name="prev.ending.colnum">
      <xsl:choose>
        <xsl:when test="$prev.entry">
          <xsl:call-template name="entry.ending.colnum">
            <xsl:with-param name="entry" select="$prev.entry"/>
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>0</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <xsl:call-template name="add-empty-entries">
      <xsl:with-param name="number">
        <xsl:choose>
          <xsl:when test="$prev.ending.colnum = ''">0</xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$entry.colnum - $prev.ending.colnum - 1"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:with-param>
    </xsl:call-template>
  </xsl:if>

  <xsl:element name="{$cellgi}">

  <xsl:if test="@spanname">
   <xsl:variable name="namest"
select="ancestor::tgroup/spanspec[@spanname=./@spanname]/@namest"/>
<xsl:variable name="nameend"
select="ancestor::tgroup/spanspec[@spanname=./@spanname]/@nameend"/>
<xsl:variable name="colst"
select="ancestor::*[colspec/@colname=$namest]/colspec[@colname=$namest]/@col
num"/>
<xsl:variable name="colend"
select="ancestor::*[colspec/@colname=$nameend]/colspec[@colname=$nameend]/@c
olnum"/>
<xsl:attribute name="colspan"><xsl:value-of 
  select="number($colend)
-
number($colst) + 1"/></xsl:attribute>
  </xsl:if>

    <xsl:if test="@morerows">
      <xsl:attribute name="rowspan">
        <xsl:value-of select="@morerows+1"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@namest">
      <xsl:attribute name="colspan">
        <xsl:call-template name="calculate.colspan"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@align">
      <xsl:attribute name="align">
        <xsl:value-of select="@align"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@char">
      <xsl:attribute name="char">
        <xsl:value-of select="@char"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@charoff">
      <xsl:attribute name="charoff">
        <xsl:value-of select="@charoff"/>
      </xsl:attribute>
    </xsl:if>
    <xsl:if test="@valign">
      <xsl:attribute name="valign">
        <xsl:value-of select="@valign"/>
      </xsl:attribute>
    </xsl:if>

<xsl:if test="@rowsep='1'">
<xsl:attribute name="style">border-bottom:thin solid
black</xsl:attribute>
</xsl:if>

    <xsl:if test="not(preceding-sibling::*)
                  and ancestor::row/@id">
      <a name="{ancestor::row/@id}"/>
    </xsl:if>

    <xsl:if test="@id">
      <a name="{@id}"/>
    </xsl:if>

    <xsl:choose>
      <xsl:when test="$empty.cell">
        <xsl:text>&#160;</xsl:text>
      </xsl:when>
      <xsl:otherwise>
        <xsl:apply-templates/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:element>
</xsl:template>

<xsl:template name="add-empty-entries">
  <xsl:param name="number" select="'0'"/>
  <xsl:choose>
    <xsl:when test="$number &lt;= 0"></xsl:when>
    <xsl:otherwise>
      <td>&#160;</td>
      <xsl:call-template name="add-empty-entries">
        <xsl:with-param name="number" select="$number - 1"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<xsl:template name="entry.colnum">
  <xsl:param name="entry" select="."/>

  <xsl:choose>
    <xsl:when test="$entry/@colname">
      <xsl:variable name="colname" select="$entry/@colname"/>
      <xsl:variable name="colspec"

select="$entry/ancestor::tgroup/colspec[@colname=$colname]"/>
      <xsl:call-template name="colspec.colnum">
        <xsl:with-param name="colspec" select="$colspec"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="$entry/@namest">
      <xsl:variable name="namest" select="$entry/@namest"/>
      <xsl:variable name="colspec"
select="$entry/ancestor::tgroup/colspec[@colname=$namest]"/>
      <xsl:call-template name="colspec.colnum">
        <xsl:with-param name="colspec" select="$colspec"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="count($entry/preceding-sibling::*) = 0">1</xsl:when>
    <xsl:otherwise>
      <xsl:variable name="pcol">
        <xsl:call-template name="entry.ending.colnum">
          <xsl:with-param name="entry"
select="$entry/preceding-sibling::*[1]"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:value-of select="$pcol + 1"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<xsl:template name="entry.ending.colnum">
  <xsl:param name="entry" select="."/>

  <xsl:choose>
    <xsl:when test="$entry/@colname">
      <xsl:variable name="colname" select="$entry/@colname"/>
      <xsl:variable name="colspec"
select="$entry/ancestor::tgroup/colspec[@colname=$colname]"/>
      <xsl:call-template name="colspec.colnum">
        <xsl:with-param name="colspec" select="$colspec"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="$entry/@nameend">
      <xsl:variable name="nameend" select="$entry/@nameend"/>
      <xsl:variable name="colspec"
select="$entry/ancestor::tgroup/colspec[@colname=$nameend]"/>
      <xsl:call-template name="colspec.colnum">
        <xsl:with-param name="colspec" select="$colspec"/>
      </xsl:call-template>
    </xsl:when>
    <xsl:when test="count($entry/preceding-sibling::*) = 0">1</xsl:when>
    <xsl:otherwise>
      <xsl:variable name="pcol">
        <xsl:call-template name="entry.ending.colnum">
          <xsl:with-param name="entry"
select="$entry/preceding-sibling::*[1]"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:value-of select="$pcol + 1"/>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<xsl:template name="colspec.colnum">
  <xsl:param name="colspec" select="."/>
  <xsl:choose>
    <xsl:when test="$colspec/@colnum">
      <xsl:value-of select="$colspec/@colnum"/>
    </xsl:when>
    <xsl:when test="$colspec/preceding-sibling::colspec">
      <xsl:variable name="prec.colspec.colnum">
        <xsl:call-template name="colspec.colnum">
          <xsl:with-param name="colspec"
                          select="$colspec/preceding-sibling::colspec[1]"/>
        </xsl:call-template>
      </xsl:variable>
      <xsl:value-of select="$prec.colspec.colnum + 1"/>
    </xsl:when>
    <xsl:otherwise>1</xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="generate.colgroup">
  <xsl:param name="cols" select="1"/>
  <xsl:param name="count" select="1"/>
  <xsl:choose>
    <xsl:when test="$count>$cols"></xsl:when>
    <xsl:otherwise>
      <xsl:call-template name="generate.col">
        <xsl:with-param name="countcol" select="$count"/>
      </xsl:call-template>
      <xsl:call-template name="generate.colgroup">
        <xsl:with-param name="cols" select="$cols"/>
        <xsl:with-param name="count" select="$count+1"/>
      </xsl:call-template>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="generate.col">
  <xsl:param name="countcol">1</xsl:param>
  <xsl:param name="colspecs" select="./colspec"/>
  <xsl:param name="count">1</xsl:param>
  <xsl:param name="colnum">1</xsl:param>

  <xsl:choose>
    <xsl:when test="$count>count($colspecs)">
      <col/>
    </xsl:when>
    <xsl:otherwise>
      <xsl:variable name="colspec" select="$colspecs[$count=position()]"/>
      <xsl:variable name="colspec.colnum">
        <xsl:choose>
          <xsl:when test="$colspec/@colnum">
            <xsl:value-of select="$colspec/@colnum"/>
          </xsl:when>
          <xsl:otherwise>
            <xsl:value-of select="$colnum"/>
          </xsl:otherwise>
        </xsl:choose>
      </xsl:variable>

      <xsl:choose>
        <xsl:when test="$colspec.colnum=$countcol">
          <col>
            <xsl:if test="$colspec/@align">
              <xsl:attribute name="align">
                <xsl:value-of select="$colspec/@align"/>
              </xsl:attribute>
            </xsl:if>
            <xsl:if test="$colspec/@char">
              <xsl:attribute name="char">
                <xsl:value-of select="$colspec/@char"/>
              </xsl:attribute>
            </xsl:if>
            <xsl:if test="$colspec/@charoff">
              <xsl:attribute name="charoff">
                <xsl:value-of select="$colspec/@charoff"/>
              </xsl:attribute>
            </xsl:if>
          </col>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="generate.col">
            <xsl:with-param name="countcol" select="$countcol"/>
            <xsl:with-param name="colspecs" select="$colspecs"/>
            <xsl:with-param name="count" select="$count+1"/>
            <xsl:with-param name="colnum">
              <xsl:choose>
                <xsl:when test="$colspec/@colnum">
                  <xsl:value-of select="$colspec/@colnum + 1"/>
                </xsl:when>
                <xsl:otherwise>
                  <xsl:value-of select="$colnum + 1"/>
                </xsl:otherwise>
              </xsl:choose>
            </xsl:with-param>
           </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:otherwise>
  </xsl:choose>

</xsl:template>

<xsl:template name="colspec.colwidth">
  <!-- when this macro is called, the current context must be an entry -->
  <xsl:param name="colname"></xsl:param>
  <!-- .. = row, ../.. = thead|tbody, ../../.. = tgroup -->
  <xsl:param name="colspecs" select="../../../../tgroup/colspec"/>
  <xsl:param name="count">1</xsl:param>
  <xsl:choose>
    <xsl:when test="$count>count($colspecs)"></xsl:when>
    <xsl:otherwise>
      <xsl:variable name="colspec" select="$colspecs[$count=position()]"/>
      <xsl:choose>
        <xsl:when test="$colspec/@colname=$colname">
          <xsl:value-of select="$colspec/@colwidth"/>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="colspec.colwidth">
            <xsl:with-param name="colname" select="$colname"/>
            <xsl:with-param name="colspecs" select="$colspecs"/>
            <xsl:with-param name="count" select="$count+1"/>
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>

<xsl:template name="calculate.colspan">
  <xsl:param name="entry" select="."/>
  <xsl:variable name="namest" select="$entry/@namest"/>
  <xsl:variable name="nameend" select="$entry/@nameend"/>

  <xsl:variable name="scol">
    <xsl:call-template name="colspec.colnum">
      <xsl:with-param name="colspec"
select="$entry/ancestor::tgroup/colspec[@colname=$namest]"/>
    </xsl:call-template>
  </xsl:variable>
  <xsl:variable name="ecol">
    <xsl:call-template name="colspec.colnum">
      <xsl:with-param name="colspec"

select="$entry/ancestor::tgroup/colspec[@colname=$nameend]"/>
    </xsl:call-template>
  </xsl:variable>
  <xsl:value-of select="$ecol - $scol + 1"/>
</xsl:template>

</xsl:stylesheet>


11.

Graphic file format in XSL stylesheets

Bob Stayton

It appears that TIFF files are not supported in the current DocBook XSL stylesheets. The test for graphics format looks like this in graphics.xsl:

<xsl:template name="is.graphic.format">
  <xsl:param name="format"></xsl:param>
  <xsl:if test="$format = 'PNG'
                or $format = 'JPG'
                or $format = 'JPEG'
                or $format = 'linespecific'
                or $format = 'GIF'
                or $format = 'GIF87a'
                or $format = 'GIF89a'
                or $format = 'BMP'">1</xsl:if>
</xsl:template>

So these are the file formats presently supported.

12.

No en localization errors

Bob Stayton

> No "en" localization of "TableofContents" exists; using "en".
> No "en" localization of "TableofContents" exists; using "en".
> No "en" localization of "table" exists; using "en".
> No "en" localization of "TableofContents" exists; using "en".
> No "en" localization of "table" exists; using "en".
> No "en" localization of "table" exists; using "en".
> No "en" localization of "colophon" exists; using "en".

This message comes from the system of text templates for localizing generated text, such as "Table of Contents". It comes from common/l10n.xsl, based on the text templates in common/en.xml and such. For some reason, your setup isn't finding the right text templates.

Are you sure you are using the 1.48 or later stylesheets? That redundant part of the message was fixed in version 1.48, so it should read:

No "en" localization of "TableofContents" exists.

13.

Breaking long strings such as url's

Paul Tyson

One should also be able to insert &shy; (which is defined in the character entity files that are part of the DocBook DTD--or you can just use &#173;) to insert a discretionary hyphen. This will cause a hyphen (dash) character to be printed at the end of the line if a break is taken here.

One can also insert &#8203; which is the "zero width space" character which allows a line break here without the insertion of a dash. (This character may not be implemented as such in all formatters.)

In both cases, if the line isn't broken at that spot, your output doesn't have an introduced space as would be the case with solution 1.

14.

Using changebars and chunk.xsl together



> Is it possible to use both chunk.xsl and changebars.xsl? If I import them
> both, no matter in what order, the changebars stylesheet won't have any effect.

> The only workaround I could find was to import changebars.xsl into
> docbook.xsl by adding an <xsl:import> line, and remove the line which
> imports docbook.xsl in changebars.xsl.

> Is there a cleaner way to do it?

Make your own copy of changebars.xsl (e.g. changebars-chunk.xsl) and change <xsl:import href="docbook.xsl"/> to <xsl:import href="chunk.xsl"/>. It should (could;-) work.

15.

Does stylesheet processing validate the source document?

Bob Stayton


> I don't *think* that xsltproc validates, but I may be wrong.  There is
> xmllint for validation though.

That's correct, xsltproc does not validate. It only uses the DOCTYPE to resolve any entities it finds in the content. I don't think Saxon validates either.

XSLT processors are designed to handle well-formed documents in addition to valid documents. So it really isn't their job to determine if a document is valid.

16.

The Unicode Bidirectional Algorithm

Tony Graham

The Unicode Bidirectional Algorithm in a nutshell...

Bidirectional types

Unicode characters have a "bidirectional type". There's lots of types, but they're divided into three categories: strong, weak, and neutral.

Characters with a strong bidirectional type really know their directionality. For example, the characters in most alphabets are "strongly" left-to-right, and the characters in the Hebrew and Arabic alphabets (and some others) are "strongly" right-to-left.

Characters with a weak bidirectional type determine their directionality according to their proximity to other characters with strong directionality.

Characters with a neutral bidirectional type determine their directionality from either the surrounding strong text or the embedding level.

Embedding levels

The Unicode Bidirectional Algorithm works in terms of "levels" of right-to-left text embedded with left-to-right text, and vice versa.

Even levels (0, 2, 4...60) are left-to-right. Odd levels (1, 3..61) are right-to-left.

Text at an even level is rendered left-to-right. Text at an odd level is rendered right-to-left.

The Unicode Bidirectional Algorithm works on paragraphs, so the first step is dividing text into paragraphs. You determine the "paragraph embedding level" by finding the first character in the paragraph with a strong bidirectional category. If the character is strongly left-to-right, the paragraph embedding level is 0, otherwise (i.e. if the character is strongly right-to-left), the embedding level is 1.

Embedding goes on from there: contained text with the opposite directionality is at the next embedding level, and text with the original directionality that is contained by the text with the opposite directionality is at the next lowest embedding level.

Explicit bidirectional formatting

Unicode includes characters for fudging the embedding level:

- RLE, Right-to-Left Embedding, says treat the following text as right-to-left. I.e., it forces the embedding level to the next lowest odd number: level 0 -> level 1; 1 or 2 -> 3, etc.
- LRE, Left-to-Right Embedding, says treat the following text as left-to-right. I.e., it forces the embedding level to the next lowest even number: 0 or 1 -> 2; 2 or 3 -> 4, etc.
- RLO, Right-to-Left Override, says treat the following characters as strong right-to-left characters. I.e. it forces an odd embedding level, but it also sets the "override status" to right-to-left so the implementation knows which way to push those neutral types.
- LRO, Left-to-Right Override, says treat the following characters as strong left-to-right characters. I.e. it forces an even embedding level, but it also sets the "override status" to left-to-right so the implementation knows which way to push those neutral types.
- PDF, Pop Directional Format, is the generic "end-tag" for the previous RLE, LRE, RLO, or LRO character.
- RLM, Right-to-Left Mark, is a zero-width (i.e. it doesn't print) character that is used as an invisible spot of strong right-to-left directionality to coerce neighbouring weak and neutral characters into behaving the way you want. This doesn't change the embedding level.

The example in the Unicode Standard shows RLM being used with an exclamation mark (i.e., '!') that is between some left-to-right text and some neutral text, all of which is within some right-to-left text. Without the RLM, the ! is treated as part of the span of left-to-right text. With the RLM between the left-to-right text and the !, the ! is treated as part of the right-to-left text, which changes on which end of the left-to-right text it is rendered.

- LRM, Left-to-Right Mark, is a zero-width (i.e. it doesn't print) character that is used as an invisible spot of strong left-to-right directionality to coerce neighbouring weak and neutral characters into behaving the way you want. This doesn't change the embedding level.

RLM and LRM are good if you know what you're doing, you probably have an editor that lets you represent them, and you're worried about conserving embedding levels. For the rest of us, the other five characters represent the brute-strength and ignorance approach that we're more comfortable with.

Bidirectional conformance

Systems do not need to support any explicit directional formatting codes.

The "implicit bidirectional algorithm" can be taken as handling bidirectionality based solely on embedding levels and the characters' bidirectionality types and without any overrides.

There isn't an "explicit bidirectional algorithm" as such. The explicit codes distort the embedding levels compared to what they would ordinarily be, but after they've been taken into account, the "implicit" algorithm, based on embedding levels and characters' types, is what finally determines which text is rendered in which direction.

Higher-level protocols

The "permissible ways for systems to apply higher-level protocols to the ordering of bidirectional text" are:

- Override the paragraph embedding level
- Override the number handling to use information provided by a broader context (Let's not go there.)
- Replace, supplement, or override the bidirectional overrides or embedding codes
- Override the bidirectional character types assigned to control codes to match the interpretation of the control codes used within the protocol (Let's not go there either.)
- Remap the number shapes to match those of another set (Ditto.)

HTML, CSS, and XSL do the first and third only.

HTML

HTML has a "dir" attribute for indicating the direcionality of text. The allowed values are RTL and LTR. I.e., "dir" overrides the paragraph embedding level and replaces the embedding codes.

HTML also has a <bdo> element that is used for overriding the effects of the bidirectional algorithm on a span of text. I.e., it replaces the override codes.

The HTML Recommendation warns against mixing its controls with explicit bidirectional override characters. Hardly surprising.

CSS2

As Paul noted, CSS has a "direction" property with values "ltr" and "rtl" (and "inherit"). It specifies "the base writing direction of blocks and the direction of embeddings and overrides for the Unicode BIDI algorithm." I.e., it overrides the paragraph embedding level for blocks (i.e., for what Unicode considers paragraphs) and it's also used for replacing the bidirectional overrides and embedding codes.

The "unicode-bidi" property is the other half of how CSS2 replaces the bidirectional overrides and embedding codes. The allowed values are "normal", "embed", "override", and "inherit".

'unicode-bidi: normal' doesn't do anything, which is why 'normal' is the default value.

'unicode-bidi: embed' is equivalent to RLE (when 'direction: rtl') or LRE (when 'direction: ltr') at one end of a span of text and a PDF of the other.

'unicode-bidi: override' is equivalent to RLO (when 'direction: rtl') or LRO (when 'direction: ltr') at one end of a span of text and a PDF of the other.

XSL

XSL has "direction", "unicode-bidi" and "writing-mode" properties, although they don't all apply to all the same formatting objects.

"writing-mode" applies to the formatting objects that set up a "reference-area", i.e., to the big-picture formatting objects that specify the page, the regions with the page, to tables, and to table cells. It affects how you sequence blocks of text, but it also overrides the "paragraph embedding level."

"direction" and "unicode-bidi" apply only to the "bidi-override" formatting object. They behave pretty much like in CSS2, except that the inital value of "direction" is derived from the current "writing-mode" value rather than being explicitly "ltr".

(Determing the initial value of "direction" this way probably means fewer surprises when formatting a purely right-to-left document, but the "direction" description does read like it was written for "direction" to apply to more formatting objects than just "bidi-override".)

Conclusion

1. If using markup to control bidirectionality, you need a way to set the paragraph embedding level (i.e., set whether the paragraph starts out right-to-left or left-to-right) as well as a way to override the implicit bidirectional algorithm (the algorithm that works w.r.t. the characters' bidirectional types).

2. Markup that overrides the implicit bidirectional algorithm should support both overrides (RLO and LRO equivalent) and embeds (RLE and LRE equivalent).

3. Include strong words against mixing markup-based bidirectionality controls and the explicit bidirectionality characters.

4. Consistency with existing standards is a GOOD THING. Compatibility with the Unicode Bidirectional Algorithm is essential.

5. Work out whether every inline can affect bidirectionality (CSS style) or whether there's one special-purpose element (HTML and XSL style, although I don't expect XHTML to stick to that and it doesn't matter for HTML anyway if you're also using CSS).

6. A politically correct default direction is hard to determine. CSS2 uses 'ltr', and XSL lets the XSL processor have a default.

17.

Seperating footnotes from body text

David Tolpin



> I'd like to have a leader separating the body from the
> footnotes, like:

>   This is some text in the flow.
>   -------
>   1. First footnote.
>   2. Second footnote.

> I have a <footnote> element (inline) and a matching template in the XSL,
> but if I put the leader there there will be leaders between each footnote
> of course.

this is simple and standard.

<fo:static-content flow-name="xsl-footnote-separator">
  <fo:block>
   <fo:leader leader-pattern="rule" 
    leader-length="100%" rule-thickness="0.5pt" 
    rule-style="solid" color="black"/>
  </fo:block>
  </fo:static-content>

18.

XHTML table output

Bob Stayton




> I'm looking for a way to transform my docbook dtd, especially for tables.
> In fact i'd like my docbook tables to be validated by the xhtml1.0 dtd
> does somebody know if it's possible to do this?
> thanks for your help

There are two XHTML 1.0 DTDs, Transitional XHTML and Strict XHTML. By default, the DocBook stylesheets produce Transitional XHTML, and it should be valid if you supply alt attributes on all your images. Instances of output that is not valid Transitional XHTML should be reported as bugs.

Strict XHTML is harder. There is currently no parameter to turn on Strict XHTML output from the DocBook XSL stylesheets. It is possible to specify the Strict DTD in the output DOCTYPE, but the output may not be valid. It somewhat depends on what attributes you use in your XML files, and what parameters you use during processing.

19.

Insert date into output

Jirka Kosek



> Does anyone know a customization that will modify my user.head.content to
> autogenerate the date of the transform in the HTML <meta> tags?

Add following code into your customized template user.head.content:

<meta name="date">
   <xsl:attribute name="content">
     <xsl:call-template name="datetime.format">
       <xsl:with-param name="date" select="date:date-time()"/>
       <xsl:with-param name="format" select="m/d/Y"/>
     </xsl:call-template>
   </xsl:attribute>
</meta>

Don't forget to declare date namespace as xmlns:date="http://exslt.org/dates-and-times" and to either choose a processor that has the exslt built in, or get the code from exslt.org

20.

Admonition styling

Bob Stayton



>   with a simple test file, i created some admonitions and
> defined the xsl:params admon.graphics and admon.graphics.extension,
> and 

> 1) converted XML to FO with xsltproc
> 2) converted FO to PDF with FOP

>   now, each of the admonitions has *both* a text label and a
> graphic.  can i dump the text and just retain the graphic?
> i thought that was the default behavior.

I asked Norm about this a couple of months ago. The DSSSL stylesheets always did one or the other. But the XSL stylesheets have had both the word and the graphic (when turned on) from their first release. He thought it was probably a bug, but since it has been in use for so long, some people expect the word to be there too, so just turning it off seems like a bad idea. That's as far as we got, and no changes were made.

Perhaps there should be a new parameter that would turn off the text label. Maybe 'admon.textlabel' with 1 (on) as the default to retain the current behavior.

In the mean time, you could try the following crude workaround in a customization layer:

<xsl:template match="note|important|warning|caution|tip"
              mode="object.title.markup">
</xsl:template>

The 'graphical.admonition' template processes the note element in object.title.markup mode to get either the explicit <title> element if it has one or the generated text label "Note". Making this an empty template like this will deliver no text at that point. It is kind of a crude solution, and I don't know if there would be side effects. I don't think that mode is used in other places for admonitions because their titles don't appear in the table of contents, and it would be rare to xref to one.

21.

CSS styling on tables

David Cramer



>I have documents created with DocBook (+ XSL stylesheets) and Website.
>If I write "body { font-size: 12px; }" - the font size of tables doesn't 
>change in documents created with DocBook.
>But the same statement works fine for websites created with WebSite.

Put this in your css to make tables inherit your font settings:

/* Rule to fix quirks-mode inheritance behavior */
table, caption {
  font-size: inherit;
  font-weight: inherit;
  font-style: inherit;
  font-variant: inherit;
}

For the explanation see: devedge.netscape.com

Off topic, but I think setting font size absolutely is a bad idea. It's not nice for unfortunate souls who use IE and want to set their screen resolution to 1600x1200.

Well, that trick works for Opera and Mozilla, but not for IE. Still, the difference you're seeing is the difference between compliance mode and compatiblity/quirks mode. The website output is xhtml and the presense of the doctype puts newer browsers in compliance mode, so font-size inherits to table. The other output is just html, so newer browsers go into quirks/compatility mode and font-size isn't inherited by table. Lots of stuff written about it: article

What you do depends on what browsers you need to support etc.

22.

Including SVG in docbook

Jens ??



> I try to integrate SVG figure in docbook book. Has
> anybody already done this? Is there howto on this?
> Thanks for your help,

Really simple, if you use external files. Just do exactly what you would do with a PNG file.

If however you want to embed the svg into a docbook document, you need to use Norms SVG extensiom (see http://docbook.org).

Note, hoever, that e.g. although FOP and Batik works quite nicely together, you will not yet be able to use all SVG elements. Partly because the integration isn't perfect yet, and partly due to limitations in the PDF format. I have no experience with XEP/Anthenna House and SVG yet.

(ed. SVG is supported in XEP)

As always, check Bob Staytons book (Bobs pages) in chater 15, which normally has an answer to everything you ever want to ask about docbook.

23.

Segmented list decoration

Bob Stayton




> Do anyone have any XSLs trick for segmentedlists?  I would like each 
> group to be delimited by a horizontal rule or some kind of separation.

> i.e.  I get

> Attribute: cginewfrmok
> Value:
> Constraint:
> Explanation: Message to be displayed on a separate page whenever an
> operation was successful. Used
> whenever cgirefreshform is NO.
> Attribute: cgirefreshok
> Value:
> Constraint:
> Explanation: Message to be displayed on an input form when an update is
> successful. Used whenever
> cgirefreshform is YES.



> where I would like

> Attribute: cginewfrmok
> Value:
> Constraint:
> Explanation: Message to be displayed on a separate page whenever an
> operation was successful. Used
> whenever cgirefreshform is NO.
> -------------------------------------------------------------------------------------------------------
> Attribute: cgirefreshok
> Value:
> Constraint:
> Explanation: Message to be displayed on an input form when an update is
> successful. Used whenever
> cgirefreshform is YES.

You want to customize this template in lists.xsl:

<xsl:template match="seglistitem">
  <xsl:apply-templates/>
</xsl:template>

For HTML output, it could be:

<xsl:template match="seglistitem">
  <!-- rule above for first one only -->
  <xsl:if test="not(preceding-sibling::seglistitem)">
    <hr/>
  </xsl:if>
  <xsl:apply-templates/>
  <hr/>
</xsl:template>

24.

Processing docbook, catalogs, Xinclude and XSLT processor

Bob Stayton



>The command line parameters for an XSLT processor, Xinclude
>and using a catalog are quite complex. Are they documented anywhere?

Actually, this bit made it into my book at the last minute. See: sagehill.net

25.

Localisation in seperate files

Eliot Kimber



> Currently I have one external variables file that stores all
> boilerplate text for 15 languages. 
> I use the xsl:include statement as the first thing in my main
> stylesheet.  <xsl:include href='fo-variables.xsl'/>

> I would like to change this to a separate file for every language to
> ease in translating new words.

> I would like to do this:
> <xsl:if test="@language='french'"><xsl:include
> href='french.xsl'/></xsl:if>
> <xsl:if test="@language='greek'"><xsl:include href='greek.xsl'/></xsl:if>

> How do I do an if statement or choose statement to only include the
> corresponding language file?

You can't.

A better way to approach this problem is probably to use a separate XML document with the translations that you then get as needed, rather than using statically-defined variables. For example, if you name your files with the language code, then you can do something like this:

<xsl:variable name="langCode" select="/*/@xml:lang"/>
<xsl:variable name="boiler-plate-item-one"
      select="document(concat('trans/boilerplate_',
                              $langCode,
                              '.xml'),.)/boilerplate[@id = 'item-01']/>

This will select the <boilerplate> element with the ID "item-01" from the file "./trans/boilerplate_zh-CN.xml" [relative to the current document, leave out the ",." parameter of document() if you want the URL to be relative to the stylesheet] if the value of the root element's xml:lang= attribute is "zh-CN".

26.

Docbook to text. Method 1.

David ??

Btw., here's my version of that. It currently relies on a saxon extension to perform a second pass on the output and cleanup a problem with extra lines after bullets and numbers in lists.

1. Use Saxon to run html2txt.xsl (cleanup.xsl must be in the same directory) on the docbook file.

2. Run "links -dump filename.html | tr -d '\000' > filename.txt" (or links -dump filename.html | tr -d '\000' | unix2dos > filename.txt if you expect people to use notepad to open the file.)

The main annoyance left is with programlistings. If you have a programlisting in a listitem, the programlisting is flush left even tho the listitem is indented.

I don't do anything with formatting of inlines and can't remember what happens with ulinks, but maybe this can help you get stared.

===============================================================
html2txt.xsl
===============================================================
<?xml version="1.0" encoding="US-ASCII"?>

<xsl:stylesheet
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  xmlns:saxon="http://icl.com/saxon"
  version="1.0">

<xsl:import href="http://docbook.sourceforge.net/release/
xsl/1.60.1/xhtml/docbook.xsl"/>

<xsl:output   
	method="xml"
	encoding="us-ascii"
	saxon:next-in-chain="cleanup.xsl"/>

<xsl:param name="appendix.autolabel" select="1"/>
<xsl:param name="chapter.autolabel" select="1"/>
<xsl:param name="part.autolabel" select="1"/>
<xsl:param name="preface.autolabel" select="1"/>
<xsl:param name="section.autolabel" select="1"/>
<xsl:param name="admon.graphics" select="0"/>
<xsl:param name="callout.graphics" select="'0'"/>
<xsl:template match="index|figure|informalfigure|mediaobject" priority="1000"></xsl:template>

<xsl:param name="generate.toc">
appendix  toc
article   toc
book      toc
chapter   toc
part      toc
preface   toc
qandadiv  toc
qandaset  toc
reference toc
section   toc
set       toc
</xsl:param>


</xsl:stylesheet>

cleanup.xsl:

<?xml version="1.0" encoding="US-ASCII"?>

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

	<xsl:output
	encoding="us-ascii"
	  method="xml"
	  indent="yes"/>

    <xsl:template match="@*|node()">
      <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
      </xsl:copy>
    </xsl:template>

  <xsl:template match="xhtml:li/xhtml:p[1]">
	<xsl:apply-templates select="node()"/>
  </xsl:template>

</xsl:stylesheet>

27.

Table of Content

Bob Stayton

Here is a basic outline of how a book TOC works, and I hope it helps you see how you might customize the process to add a new element.

1. The template with match="book" calls a template named 'division.toc' to start the process.

2. The division.toc template in autotoc.xsl selects into a variable named 'nodes' which elements are to appear at the top level of the book toc. These include chapter, appendix, glossary, index, etc. Then it generates the TOC titlepage (basically just the "Table of Contents" title at the top of the page).

3. Then it applies templates to the selected elements using mode="toc". So you need to find how each element is processed in mode="toc" to see what happens next.

4. Also in autotoc.xsl, there is a template with match="preface|chapter|appendix|article" with mode="toc". It processes the current element by calling the template named 'toc.line', which generates a single line in the TOC.

5. Then it selects which of its child elements are to be subheadings under the current element and stores them in a 'nodes' variable. If there are such nodes to be processed, it sets an indent and applies templates to those nodes, also in mode="toc".

This process continues to the next level and then the next, to the limit of the sections that are designated to be included in the TOC. As you can see, it is a recursive process that generates the TOC, descending down through the hierarchy of elements to create a similar hierarchy in the TOC.

To include other elements not already accounted for in the TOC, you need to add them to the 'nodes' selection at the appropriate point. This would most likely be in the templates that match on section elements in mode="toc". So you would copy that template to your customization layer and change which nodes are selected.

Then you need to supply a new template that matches that element name and in mode="toc". It should be similar to the others in that mode. Since your para element doesn't seem to have children that should appear in the toc, calling the toc.line template may be enough.

To actually generate the text for the element in the toc, you should look at the toc.line template. It works by applying templates to the current element in mode="titleabbrev.markup". Such templates already exist for any titled elements in Docbook, but your paragraph elements wouldn't have titles. So you need to add a template in that mode that matches your selected para elements.

You are correct that the TOC machinery calls a lot of templates, but it does that because it is designed to be modular and recursive, instead of a single monolithic procedure. The key is to find the appropriate entry points and modular templates to modify, and that lets you minimize the amount of code in your customization layer.