oXygen XML Editor

Docbook XSL-FO Stylesheets

1. PDF output from Docbook
2. How to insert a pagebreak into docbook output
3. Cross references to page numbers
4. XEP 2.7 (October 2001 Rec) and xsl-fo stylesheets
5. Running footer in article
6. Tables in fop
7. Handling long url's in pdf output
8. Custom Footers in XSL-FO
9. Using pagemasters for n column output in XSL-FO output.
10. Page numbers appear as ??
11. Page break for images
12. Indentation in xsl-fo
13. fo marker problem
14. fo to RTF using jfor, % units not working
15. appendix doesn't start a new page in XSL-FO output?
16. Creating boxed programlisting, xsl-fo output.
17. Blank page layout
18. XEP with catalog support for fo output
19. Custom footer in fo output
20. Sidebar, in XSL-FO
21. Breaking long lines in pdf output
22. revhistory not shown in pdf output
23. Pagebreaks in FO output
24. How can I set the Font size of <programlisting>s
25. Superscript font size in XSL-FO output
26. Titled figures, spacing
27. Cross references, how to modify layout
28. Image quality in PDF output
29. Accentuate or indent wrapped lines
30. Align tables by decimal content
31. Using greek characters with docbook and fop
32. Procedure Step Numbering
33. para customisation
34. Getting static content into region-start and end
35. Line numbered programlisting
36. Customizing xrefstyle
37. Coloring links, PDF output
38. PDF output toc customization
39. Hyphenation, manually
40. How do I increase the column width of the inside column in a header?


PDF output from Docbook

Jirka Kosek

> I have a DocBook book written in XML and want
> convert it to PDF.  Is there a tool which will accomplish this?

There are many options. For all of them you will need DocBook stylesheets available from Sourceforge

1. You can use DSSSL stylesheets with Jade and then pdfJadeTeX to get PDF
2. You can use XSL FO stylesheets and some FO procesor (e.g. PassiveTeX) to get PDF. You will also need some XSLT procesor (e.g. Saxon, XT, Xalan) for applying FO stylesheet on your document.
3. You can use DSSSL stylesheet and Jade to get RTF version of your document. Using MS Word and Adobe Distiller you can get PDF from your RTF file.

The list is not complete, but these are probably most commonly used ways to get PDF from DocBook source.


How to insert a pagebreak into docbook output

Michael Smith

The answer's been that you need to use a processing instruction instead of an element (so also need to write support in your XSLT customization layer for generating a pagebreak in the FO output for each instance of that PI).

The suggestion from Paul Reavis on the debian-sgml list was to use <?dbfo break-before="page"?>. Something like that would work -- there's existing (undocumented) support in the stylesheets (dbfo-attribute template in fo/pi.xsl and dbhtml-attribute template in html/pi.xsl) for processing PIs that start with "dbfo" and "dbhtml" and extracting the pseudo- attributes/values from them.

As far as the rationale for the DTD not providing an element to force pagebreaks in rendered output, it's just consistent with the fact that the DTD by design provides markup only for modeling structure and content, not presentation. If a pagebreak is strictly a processing thing and has no significance to structure or content -- just something that's specific to print delivery, not to HTML or online help, etc. -- then not really appropriate to have an element for it.


Cross references to page numbers

David Cramer

For the xsl stylesheets that Norm Walsh and others maintain on sourceforge, a feature exists that will insert cross references to page numbers, but it may still only be partially implemented in the current version of the stylesheets. Turn it on with the following parameter in your customization layer:

 <xsl:param name="insert.xref.page.number" select="1"/>

Last time I looked (1.44), it was working for <glosssee>s, but not for <xref>s. If you have chapter and section numbering turned on, you can have it refer to "Section 1.2.3" Likewise, you can have your figures, tables, and procedures numbered and have the xrefs refer to those numbers.


XEP 2.7 (October 2001 Rec) and xsl-fo stylesheets

Norm Walsh

| I'm experimenting with version 2.7 of XEP on vanilla FO output from
| docbook-xsl-1.45 and 1.46-experimental.

| XEP is having trouble, generating multiple instances of 
| the following error:

| "Attribute 'master-reference' is required and must be specified for
| element type 'fo:conditional-page-master-reference'"

| I'm not up on the recommendation so I don't know if and/or whose bug
| this might be.

The master-name attribute on conditional-page-master-reference was renamed 'master-reference' sometime shortly before the REC was published.


Running footer in article

David ??

Your happy hunting ground for headers and footers is fo/pagesetup.xsl. You probably need to add article to the match in the template <xsl:template match="chapter|appendix" mode="running.head.mode">, then you can mess with the value of <xsl:variable name="head">. For footers, hack away at <xsl:template match="*" mode="running.foot.mode"> (which should already match articles) and the variable <xsl:variable name="foot">. If you add a bunch of stuff to the static-content, you probably need to increase the value of your region-before or region-after extents (in param.xsl <xsl:param name="region.before.extent" select="'12pt'"/>) to make room for the new lines.


Tables in fop

Norm Walsh

| Hello all, does anyone have a solution/workaround for DocBook tables
| not rendering at all when using a DocBook XML -> Walsh's XSL
| FO stylesheets -> FOP chain? It's probably related to the fact that
| FOP currently wants you to specify widths for tables, but I'm not
| sure.

There are extensions in the stylesheets for this. If you're using Saxon or Xalan, turn on use.extensions and tablecolumns.extension. If you aren't using a processor that supports those extensions, simply specify widths for all the columns in your document (using colspec).


Handling long url's in pdf output

Michael Smith

This document, in pdf Section "1.2 URLs and filenames" handles the case for very long URLs.

Also from Julien LETESSIER

here's the hack for XSL 1.48 (it inserts hairline-spaces between every character in an URL): add it in your XSL driver file.

The first part is a (slightly) modified version of a part of fo/xref.xsl; the second is almost exactly like the hack created by Nikolai Grigoriev found on Yahoo! group XSL-FO.

    <!-- colored / hyphenated links -->
    <xsl:template match="ulink">
        <fo:basic-link external-destination="{@url}"
                <xsl:when test="count(child::node())=0">
                    <xsl:value-of select="@url" />
                    <xsl:apply-templates />
        <xsl:if test="count(child::node()) != 0">
            <fo:inline hyphenate="true">
                <xsl:text> (</xsl:text>
                <!--<xsl:value-of select="@url"/>-->
                <xsl:call-template name="intersperse-with-zero-spaces">
                    <xsl:with-param name="str" select="@url"/>

    <!-- Actual space intercalation: recursive -->
    <xsl:template name="intersperse-with-zero-spaces">
        <xsl:param name="str"/>
        <xsl:variable name="spacechars">

        <xsl:if test="string-length($str) &gt; 0">
            <xsl:variable name="c1"
                    select="substring($str, 1, 1)"/>
            <xsl:variable name="c2"
                    select="substring($str, 2, 1)"/>

            <xsl:value-of select="$c1"/>
            <xsl:if test="$c2 != '' and
                    not(contains($spacechars, $c1) or
                    contains($spacechars, $c2))">

            <xsl:call-template name="intersperse-with-zero-spaces">
                <xsl:with-param name="str" select="substring($str, 2)"/>


Custom Footers in XSL-FO

Martin Stemplinger

This information is current as of DocBook XSL Version 1.53.0

      | I need to add a custom footer message for article which involves
      | the print date of the document along with the Message. To give an
      | example including the line how can I do it ? Where do I need to fix ?
      | bla bla blabla bla blabla bla blabla bla blabla bla blabla bla bla
      | _________________________________________________________________
      | Page 1                                 Printed on date /system/date
      |                         Article for XYZ      Thanks

Generation of headers and footers is controlled by three templates each in pagesetup.xsl. For the footer these are:

  • The template

    	      <xsl:template match="*" mode="running.foot.mode">

    This template takes care of the different pagemasters and calls footer.table.

  • The template <xsl:template name="footer.table">

    This templates takes three parameters pageclass (with values like titlepage), sequence (with values odd, even, first, blank) and gentext-key (with the name of the current element). It defines whether a footer is actually rendered and sets up a table with one row and three columns. It calls footer.content to fill the columns.

  • The template <xsl:template name="footer.content">

    This template contains the actual output. It takes four parameters pageclass (from footer.table), sequence (from footer.table), position (with values left,center and right) and gentext-key (from footer.table).

Most of the time the only thing you need to do is to add a custom version of footer.content to your customization layer.

For example if you want to add the latest revision number to the footer, just use:

<xsl:template name="footer.content">
<xsl:param name="pageclass" select="''"/>
<xsl:param name="sequence" select="''"/>
<xsl:param name="position" select="''"/>
<xsl:param name="gentext-key" select="''"/>

<xsl:variable name="RevInfo">
            <xsl:when test="//revhistory/revision[1]/revnumber">
      <xsl:text>Revision: </xsl:text>
              <xsl:value-of select="//revhistory/revision[1]/revnumber"/>
      <!-- nop -->

         <xsl:when test="$sequence='blank'">
            <xsl:when test="$double.sided != 0 and $position = 'left'">
              <xsl:value-of select="$RevInfo"/>

            <xsl:when test="$double.sided = 0 and $position = 'center'">
              <!-- nop -->


        <xsl:when test="$pageclass='titlepage'">
          <!-- nop: other titlepage sequences have no footer -->

        <xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='left'">

        <xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='right'">

        <xsl:when test="$double.sided = 0 and $position='right'">

        <xsl:when test="$double.sided != 0 and $sequence = 'odd' and $position='left'">
          <xsl:value-of select="$RevInfo"/>

        <xsl:when test="$double.sided != 0 and $sequence = 'even' and $position='right'">
          <xsl:value-of select="$RevInfo"/>

        <xsl:when test="$double.sided = 0 and $position='left'">
          <xsl:value-of select="$RevInfo"/>

          <!-- nop -->



Using pagemasters for n column output in XSL-FO output.

Bob Stayton

> I found the setup.pagemasters template

> How can I use left2 and right2 on my documents? Is that a parameter or a
> variable? If it's not, how I write the customization layer to use the right
> pagemasters?

The left2, right2, etc. are the named page masters predefined in DocBook XSL, along with several others. They all end up as masters at the top of each FO file. The various templates call the different masters in different contexts as needed. You use parameters to select single or double sided, one or multicolumn, and set margins. The parameters are documented at sourceforge

A sample fo customization file looks like this:

<?xml version='1.0'?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
<xsl:import href="../docbook-xsl-1.50.0/fo/docbook.xsl"/> 

<xsl:param name="double.sided" select="1"/>
<xsl:param name="column.count" select="2"/>
<xsl:param name="page.margin.inner" select="'1in'"/>
<xsl:param name="page.margin.outer" select="'0.5in'"/>
<!-- etc. -->

The 'select.pagemaster' template selects the right page master based on context and parameters. In this example, the double.sided parameters means different left and right pages, and the column.count=2 means you get left2 and right2 masters for your body pages.


Page numbers appear as ??

Yann Dirson

> The page numbers of the TOC appears as ??
> Any hints, ideas why pdfjadetex not to resolve internal
> references?

You must re-run pdfjadetex until you see no more "undefined references" messages. You may want to use a wrapper that takes care of this for you (sgml2x does, I suppose docbook-utils does as well - both are available in woody).


Page break for images

Norm Walsh

| -I publish  on PDF format, and the images make the document look
| ugly, a lot of empty spaces due images placed in the next page if they
| don't fit
| -The question here is how to organize a document to decide what
| content is on each page?

Here, alas, we run into an ugly problem. This is entirely a presentation issue and "should" be fixed with better formatting tools. In the meantime, if adding an explicit page break would help, I suggest that you do it with a processing instruction.

Add something like:


to your document and then tweak the FO stylesheets to output a page-break for that PI:

<xsl:template match="processing-instruction('jose-pagebreak')">
  <fo:block break-before='page'/>


Indentation in xsl-fo

Norm Walsh

| I have an attribute set
| <xsl:attribute-set name="normal.para.spacing">
|    <xsl:attribute name="space-before.optimum">0.1cm</xsl:attribute>
|    <xsl:attribute name="space-before.minimum">0.1cm</xsl:attribute>
|    <xsl:attribute name="space-before.maximum">0.1cm</xsl:attribute>
| </xsl:attribute-set>
| but how do I do the indentation?


  <xsl:attribute name="text-indent">0.5in</xsl:attribute>

or whatever indent you want.


fo marker problem

Bob Stayton

> Really unexpected result. I like to debug a properly formatted fo file. So 
> when testing, I usually set

>   <xsl:output method="xml" indent="yes"/>

> When removing this statement, the FOP fo:marker error-message dissapears.  

Well, the spec does say the <fo:marker> must be the first child of the block. Since a block can accept text in its content, the carriage return is treated as a child text node, making the <fo:marker> the second child. I guess this is one of the reasons the default indent="no" is used in the stylesheets.


fo to RTF using jfor, % units not working

Bob Stayton

> I would like to transform a fo file generated with the 1.53 XSL
> stylesheets to rtf. When I use jfor I get the message:

> jfor V0.7.1 - see http://www.jfor.org
> Creating input and output objects...
> Converting XSL:FO file 'novalis.fo' to RTF output 'novalis.rtf'...
> jfor.INFO:jfor V0.7.1 - setting up conversion...
> jfor.INFO:Parsing xsl:fo document...
> org.xml.sax.SAXException: IOException in IBuilder:
> org.jfor.jfor.converter.ValueConversionException:
>  conversion factor not found for '%' units

> Is there a XSL parameter to tell the XSLT not to use '%' units in the
> output ? 

There's no single parameter. In 1.53.0, the running headers and footers are created as tables, and the table column widths are specified as percentages. You could create a stylesheet customization layer and customize the templates named 'header.table' and 'footer.table' to change the units from percentages to a calculated value. Those templates are in fo/pagesetup.xsl.


appendix doesn't start a new page in XSL-FO output?

Bob Stayton

> Should not appendix be forced to start on a new page
> If appendix is not back-matter what is backmatters

In fact, the XSL FO stylesheets do not treat an appendix in an article as back matter. There is a special template in fo/component.xsl with match="article/appendix" that processes the appendix as if it were a section. It doesn't start a new page-sequence. I think that is because the content model for article has appendix as a sibling of sect1, which differs from the book content model where appendix is a component (chapter, etc.).

An article is processed in fo as a single page-sequence (its template starts and ends a page-sequence, with all its content in between). You would have to customize the article template as well as the article/appendix template to stop the article page sequence and start a new page sequence for appendix.

You might be better off creating a book that contains an article and an appendix. Then the appendix will be treated as backmatter.


Creating boxed programlisting, xsl-fo output.

Jeff Beal

>I'm currently using the docbook 1.50 stylesheets (had problems with later
>versions, which I hope will be fixed in 1.54.1 - downloading it now!) and
>the latest version of FOP. I'm hoping to get the code samples in my
>programlistings to each display in a text box, and thought that I could
>probably get the effect I want by putting them each in a single-cell table.
>Has anyone else tried this successfully, and is there a more straightforward
>way of doing it?

You can use the monospace.verbatim.properties attribute-set to add additional FO attributes on your programlistings. (It will also affect <screen>, <literallayout>, and other "preformatted" block-level elements)

This example will create a heavy blue border around the programlistings:

<xsl:attribute-set name="monospace.verbatim.properties"
  <xsl:attribute name="font-family">
    <xsl:value-of select="$monospace.font.family"/>
  <xsl:attribute name="font-size">
    <xsl:value-of select="$body.font.master * 0.9"/>
  <xsl:attribute name="border-color">#0000FF</xsl:attribute>
  <xsl:attribute name="border-style">solid</xsl:attribute>
  <xsl:attribute name="border-width">heavy</xsl:attribute>

You can also add background color (<xsl:attribute name="background-color">#F0F0F0</xsl:attribute>) or any other attribute you want.


Blank page layout

Norm Walsh

| In my working environment, it is often required that blank pages are
| not so blank. I.e. we frequently put the following line "This page is
| intentionally left blank." on blank pages.

Rather than having a parameter, I just have a blank.page.content template that outputs an empty fo:block by default. You can redefine it in a customization layer to output any text you want.


XEP with catalog support for fo output

Alexander Peshkov

MB> I have some trouble of the sort

> I get the error message
{?Could not retrieve image from 
java.net.NoRouteToHostException: No route to host}

> when trying to render a docbook document translated to fo with XEP. (this is 
> due to the fact that we are now firewalled and use a proxy).

Setup XML catalogs properly. Very helpful info about XML catalogs creation can be found here: sun.com Note that starting from version 3.5 XEP provides support for XML catalogs (so there is no real need for extension any more). Use of XML catalogs with XEP described in section "3.5. Resolution of External Entities and URIs" of "XEP 3.5 User Guide" (userguide.pdf, included in XEP distribution).


Custom footer in fo output

Bob Stayton

> I am trying to add a customer footer to every page (a simple
> copyright). FAQ,  said to use the
> variable <xsl:variable name="foot"/>.  I found the template
> <xsl:template match="*" mode="running.foot.mode"> inside pagesetup.xsl,
> but no mention of the variable "foot".

> Am I missing something, or is the FAQ referring to either an old or too
> new version of pagesetup.xsl?

> Any tips on getting a custom footer working w/ the RH9 xmlto chain would
> be greatly appreciated.

To customize the footers in print output, you customize the template named 'footer.content'. The original template is in fo/pagesetup.xsl. It lets you set context conditions for each of pageclass, sequence, and position.

See this reference for further explanation and an example: sagehill


Sidebar, in XSL-FO

Jeff Beal

Just in case anybody's interested, the following XSL customization creates a decent-looking side-floating sidebar in XEP with footnotes:

  <xsl:attribute-set name="sidebar.properties">
    <xsl:attribute name="width">2.5in</xsl:attribute>
    <xsl:attribute name="padding-left">1em</xsl:attribute>
    <xsl:attribute name="padding-right">1em</xsl:attribute>
    <xsl:attribute name="start-indent">2em</xsl:attribute>

  <xsl:template match="sidebar">
    <fo:float float="outside">
      <fo:block xsl:use-attribute-sets="sidebar.properties">
        <xsl:if test="./title">
          <fo:block font-weight="bold"
            <xsl:apply-templates select="./title"
        <xsl:if test=".//footnote">
          <fo:block font-family="{$body.font.family}"
            <xsl:apply-templates select=".//footnote"

  <xsl:template match="sidebar//footnote">
    <xsl:call-template name="format.footnote.mark">
      <xsl:with-param name="mark">
        <xsl:apply-templates select="." mode="footnote.number"/>


Breaking long lines in pdf output

David Tolpin?

>How can I break long lines in fo output?

I do something similar for long filenames (we have hyphenation turned off altogether): Insert the processing instruction as per this example

<filename class="text">/net/monolith<?sbr?>/homes/dcramer<?sbr?>/foo/bar/baz</filename>

  <xsl:template match="processing-instruction('sbr')">
      character=" "

That way you only have a break if you need it. We're using xep 2.8, which doesn't support zero width spaces, but does fine with this. Worth a try in fop.


revhistory not shown in pdf output

Bob Stayton

> 1. the  element  revhistory is ignored when I
> transform to the doc into FO 

I presume your revhistory is contained in a bookinfo or other info element. If so, then the display of revhistory is considered part of the title pages and is controlled by the titlepage template system in the stylesheets.

By default, revhistory is not turned on for books produced by fo (it is for HTML; not sure why the difference).

You need to customize a copy of the fo/titlepage.templates.xml file, generate a new titlepage.templates.xsl stylesheet module, and include that in a customization layer. See this reference for more: Bobs site


Pagebreaks in FO output

Thomas Gier

> 1. Is putting <?dbfo break-before="page"?> in my document enough or do I 
> need to do more?
> 2. If I need to do more (write a xsl template?) what's the best way to 
> do this without breaking the docbook xsl templates.
> 3. Can someone provide me with a working example for this. There seem to 
> be none available (remember I'm new to this).

From another thread, Bob Stayton states:

It is a common misunderstanding that the beginpage element is used to create a page break in the output. It doesn't. That element is used to record where there was a page break in a document before it was converted to DocBook.

(now back to the question. ed)

Q1. Add the following to your customization layer:

<!-- <?custom-pagebreak?> inserts a page break at this point -->

<xsl:template match="processing-instruction('custom-pagebreak')">
  <fo:block break-before='page'/>

Inside your XML documents you now add


where you want to add a page break.

Q2. You create a customization layer simply by changing attributes and parameters in an XSL stylesheet outside the docbook tree where you import the fo/docbook.xsl stylesheet but override the default settings there with the ones in your stylesheet(s).

Q3. There is an excellent documentation (which you perhaps have already) by Bob Stayton which is available online at Bobs pages

A paperback or eBook version is available here

I assume your tool chain already works and I try to give you an example. Create a XSL file, add the following

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

  <xsl:import ref="/path/to/docbook-xsl/fo/docbook.xsl"/>


and replace "/path/to/docbook-xsl" with your path.

Inside the xsl:stylesheet-tag you now may add your customizations which override the default values set up in the docbook-xsl stylesheets.

If you add

  <xsl:param name="paper.type" select="'A5'"/>
  <xsl:param name="double.sided">1</xsl:param>

you change the paper type to A5 and switch to double sided layout (this file would also be the right place for the custom page break from Q1 :-) ...).

Then you use this stylesheet to create FO. It imports docbook.xsl and adds your customized parameters. There are lots and lots of parameters and attributes to change the layout of your PDFs. And this mailing list is an infinite ressource of tips and help.

It is not easy to provide a working example because you first have to decide which tool chain you want to use and then set up these tools accordingly. But I think the first three chapters of Bobs book will give you a very good overview and introduction into docbook-xsl.


How can I set the Font size of <programlisting>s

Bob Stayton

If you are talking about XSL, and you are talking about print output, then you can use the attribute-set named 'monospace.verbatim.properties' to change the font size for all programlistings, as well as synopsis and screen (and literallayout if it has a role="monospaced" attribute).


Superscript font size in XSL-FO output

Paul Hoadley

> is it possible to reduce the font size of superscripts in PDF output
> (using XSL styleshettes)?

Yes. Modify the 'format.footnote.mark' template. This is also where you would implement David's suggestion. I find this works nicely:

  <xsl:template name="format.footnote.mark">
    <xsl:param name="mark" select="'?'"/>

    <xsl:attribute name="line-height-shift-adjustment">

    <fo:inline vertical-align="super" font-size="60%">
      <xsl:copy-of select="$mark"/>

The default font-size is 90%, which I find a little too large. The xsl:attribute adds the line-height-shift-adjustment to the parent block. I have not noticed this breaking anything else, but I also have not tested it very widely.


Titled figures, spacing

Thomas Gier

 > 2. I would like increased space before and after a titled figure or
 > any other formal object. I have tried all sorts of xsl stuff in my
 > customizationfile without success.

There's an attribute set named formal.object.properties [1]. Just define the space before and the space after like this:

<xsl:attribute-set name="formal.object.properties">
  <xsl:attribute name="space-before.minimum">0.5em</xsl:attribute>
  <xsl:attribute name="space-before.optimum">1em</xsl:attribute>
  <xsl:attribute name="space-before.maximum">2em</xsl:attribute>
  <xsl:attribute name="space-after.minimum">0.5em</xsl:attribute>
  <xsl:attribute name="space-after.optimum">1em</xsl:attribute>
  <xsl:attribute name="space-after.maximum">2em</xsl:attribute>

> 3. I would like figure titles to be non-bolded.

This can be done by using the formal.title.properties attribute set [2]. Here's a snippet from my customisation layer which

- sets a special font for formal titles (ScalaSans-Bold)
- defines font size
- switches off hyphenation
- defines space before and after the formal title
<xsl:attribute-set name="formal.title.properties"
   <xsl:attribute name="font-family">ScalaSans-Bold</xsl:attribute>
   <xsl:attribute name="font-size">9pt</xsl:attribute>
   <xsl:attribute name="hyphenate">false</xsl:attribute>
   <xsl:attribute name="space-before.minimum">0pt</xsl:attribute>
   <xsl:attribute name="space-before.optimum">0pt</xsl:attribute>
   <xsl:attribute name="space-before.maximum">0pt</xsl:attribute>
   <xsl:attribute name="space-after.minimum">8.5pt</xsl:attribute>
   <xsl:attribute name="space-after.optimum">9pt</xsl:attribute>
   <xsl:attribute name="space-after.maximum">9.5pt</xsl:attribute>

Simply change "ScalSans-Bold" to the name of the font you want to use.

Another way of achieving this is to set

     <xsl:attribute name="font-weight">normal</xsl:attribute>

in the above attribute set. It depends on the font(s) you use.


Cross references, how to modify layout

Thomas Gier

> I would like the crossreferences to be written as "Chapter: Foo" instead
> of "Chapter, Foo".

This can be done by changeing the generated text for this purpose [3]. Here's another snippet from my customisation layer which may get you started:

<l:context name="xref-number-and-title">
  <l:template name="sect1" style="long" text="Chapter %n %t on page %p"/>
  <l:template name="sect2" style="long" text="Chapter %n %t on page %p"/>
  <l:template name="sect3" style="long" text="Chapter %n %t on page %p"/>

  <l:template name="sect1" style="short" text="Chapter %n"/>
  <l:template name="sect2" style="short" text="Chapter %n"/>
  <l:template name="sect3" style="short" text="Chapter %n"/>

As you can see there are two different styles defined. Using "<xref linkend="some_target" xrefstyle="imperia"> results in "Chapter 1.2.3 <chapter title here> on page 123" in my document. Using "<xref linkend="some_target" xrefstyle="short"> gives me "Chapter 1.2.3".without title or page number. You can define as many styles as you like. You can name these styles (style="your-name") whatever you like, of course.


Image quality in PDF output

David Tolpin

> In my experience, it is always easier to prepare production files in such a 
> way that they are optimized for the equipment of the print shop doing your 
> production. It saves lots of time, both sides, and increases the chances of 
> getting production to the state of being a "repeatable process". This state 
> is often found in organizations that apply engineering processes to their 
> production.
> When files are not optimized, any number of tweaks may be required during 
> production, theses steps may be forgotten during future print runs. The 
> result being inconsistent quality.  

I've looked through PDF specification and generated sample images in Acrobat Distiller just to confirm.

The only difference is the way raster images are stored; namely if you have a high resolution image and target a low resolution device, the image is scaled down before embedding into PDF.

Nothing else.

And this very functionality is easily achieved with stylesheet parameters, choosing different images for different resolutions. Moreover, this solution will give better and more predictable quality.

> So, as far as I can see, providing you have Acrobat Distiller, the route to 
> obtaining PDF with a higher resolution should be something like this:

There is no such thing as PDF with higher resolution. The only difference is raster images, which are scaled down before inserting for lower resolutions.

> how do we get resolution into our PS files? I think we're back to square one.

RenderX XEP provides processing-instructions to embed printer specific commands into Postscript output. You can use DocBook customization layer to add as many as you like.


Accentuate or indent wrapped lines

Bob Stayton

I know of one way to solve this problem. There may be others.

The method I have used is to put each line of the programlisting into its own fo:block. When you do that, you can control how the line is formatted. In your case, you could indent the left margin a bit, then set the text-indent to a negative number to outdent the first line to counteract the left margin. This means the first line of a wrapped line is not indented, but any subsequent wrapped lines are indented.

In order to put each line in its own fo:block, you have to create a template for programlisting that parses the text of the programlisting. Whenever it finds a line feed, it uses that as the boundary to form a fo:block.

Below is an example of an oversimplified template for programlisting that parses its content. You should put this into the larger template for programlisting, which handles any id and other such matters.

<xsl:template match="programlisting">

  <xsl:variable name="text" select="."/>

  <xsl:call-template name="lineblock">
    <xsl:with-param name="text" select="$text"/>

<xsl:template name="lineblock">
  <xsl:param name="text" select="''"/>

    <xsl:when test="contains($text, '&#10;')">
      <fo:block wrap-option='wrap'
        <xsl:value-of select="substring-before($text, '&#10;')"/>
      <xsl:variable name="after" 
        select="substring-after($text, '&#10;')"/>

        <xsl:when test="contains($after, '&#10;')">
          <xsl:call-template name="lineblock">
            <xsl:with-param name="text" select="$after"/>
          <fo:block wrap-option='wrap'
            <xsl:value-of select="$after"/>
      <fo:block wrap-option='wrap'
        <xsl:value-of select="$text"/>


The programlisting template calls the lineblock template. The lineblock template recursively parses the string value of the programlisting, looking for line ending characters "&#10;". It then puts the substring-before into an fo:block and recurses on the remaining text.

If your programlistings have elements and not just text, then it will have to do more work to handle the elements. Of course, using a recursive template to parse the lines of a programlisting is going to slow down processing. How much it slows down depends on how long the listing is and how many you have. It may not matter much.

So this is one method for handling text displays where you want to preserve the line endings if a line is short, but if the line is too long it has to be broken so it doesn't bleed off the edge of the page. With real programlistings with nested indents on the text, it may not work very well. But at least the text won't go off the page!


Align tables by decimal content


> I am trying to figure out a way to align text inside table cells by 
> the decimal point.

You can use text-align="'.'" on the tabel cells. Note the inner quotes which is necessary for the FO processor to recognize it as a string. See W3C for more info.

If you are using FOP, you'll find that this feature is not implemented. As a portable workaround, you can use two table cells for each number. Split the number at the decimal point and put the left part into the first cell, right aligned, and the right part into the second cell, left aligned:

 <fo:block text-align="right">10</fo:block>
     <fo:block text-align="left">.001%</fo:block>


Using greek characters with docbook and fop

Justus Piater

The problem is Fop's font handling. Fop does not automatically switch fonts if a given glyph does not exist in the current font.

I've been helping myself with the following workaround: put the special character into a dedicated element, e.g.,

  <phrase role="symbol">&Omicron;</phrase>

and then put a template into your stylesheet customization that switches to a font that contains this glyph:

  <xsl:template match="phrase[@role='symbol']">
    <fo:inline font-family="Symbol">

Ugly, but works for me...


Procedure Step Numbering

David Cramer

This is the template you should override. Below, I've changed <xsl:when test="count(../step) = 1"> to <xsl:when test="count(../step) = 1 and 0 = 1"> to prevent the test from ever evaluating as true.

This one is from fo/lists.xsl; you'll have to make a similar change in <xsl:template match="procedure"> from html/lists.xsl (look for <xsl:when test="count(step) = 1">).

<xsl:template match="procedure/step|substeps/step">
  <xsl:variable name="id">
    <xsl:call-template name="object.id"/>

  <fo:list-item xsl:use-attribute-sets="list.item.spacing">
    <fo:list-item-label end-indent="label-end()">
      <fo:block id="{$id}">
        <!-- dwc: fix for one step procedures. 
             Use a bullet if there's no step 2 -->
          <xsl:when test="count(../step) = 1 and 0 = 1">
            <xsl:apply-templates select="." mode="number">
              <xsl:with-param name="recursive" select="0"/>
    <fo:list-item-body start-indent="body-start()">


para customisation

Jirka Kosek

> I like the european way of typesetting paragraphs, where
> the first paragraph after a heading isn't indented, but 
> all following paragraphs are.  Here's an idea in ASCII art:


> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> xxxxxxxxxxxxxxxxxxxxx
>    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
> xxxxxxxxxxxxxxxxxxxxxx

> So I set up a customized docbook (mydocbk.dtd) attached:

There is no DTD customization needed. Only thing you need is such modification of stylesheets that doesn't indent first para. It should be sufficient to add something like this into your customization layer:

<xsl:template match="para[1]">
   <fo:block text-indent="0em">

<xsl:template match="para">
   <fo:block text-indent="1em">


Getting static content into region-start and end

Paul Hoadley

> The body margin-right is zero because the region-end extent provides
> the right margin. You would do something mirrored for left-hand
> pages.

XSL-FO's page setup mechanism is still something I don't fully understand (despite the best efforts of Dave Pawson's "XSL-FO"), but through trial-and-error I found that setting margin-right="0pt" on the simple-page-master _and_ margin-right="{$page.margin.outer}" on the region-body were required, at least to get the output I wanted. The region-body previously had no margin-right attribute, and without it, the body did indeed extend to the far edge of the page after zeroing the right margin on the simple-page-master. (Substitute 'margin-left' and 'margin.left.outer' where appropriate for the body-even simple-page-master.)

> To get some content into your start or end regions, you need to add
> fo:static-content elements with the correct flow-names (such as
> 'xsl-region-end-first') at the top of the generated
> fo:page-sequences in your output.  This means customizing the
> templates for the elements that generate page sequences, such as
> chapter and appendix.  I found it easiest to copy the way the
> running headers are handled with 'running.head.mode' but adapt it
> for 'running.side.mode'.  I can provide more details if needed.

For the benefit of the archive, I will document how I did it. I am using 'article' as the root, so for now I am customising only the 'body' pages. This is what I have done:

1. Set up a 'user.pagemasters' template:

  <xsl:template name="user.pagemasters">
    <fo:page-sequence-master master-name="body-cms">

    <fo:simple-page-master master-name="body-first-cms"
      <fo:region-body margin-bottom="{$body.margin.bottom}"
      <fo:region-before region-name="xsl-region-before-first"
      <fo:region-after region-name="xsl-region-after-first"
      <fo:region-start region-name="xsl-region-start-first"
      <fo:region-end region-name="xsl-region-end-first"

    <!-- And so on for body-odd-cms and body-even-cms, substituting
         'left-margin' and '{$margin.left.outer}' where appropriate
         for the latter. -->

2. Set up a 'select.user.pagemasters' template:

(Something I did not initially realise here is that this template also returns the master-name for the page-sequence-master, not just the simple-page-masters.)

  <xsl:template name="select.user.pagemaster">
    <xsl:param name="element"/>
    <xsl:param name="pageclass"/>
    <xsl:param name="default-pagemaster"/>

      <xsl:when test="$default-pagemaster = 'body'">
	<xsl:value-of select="'body-cms'"/>
      <xsl:when test="$default-pagemaster = 'body-first'">
	<xsl:value-of select="'body-first-cms'"/>
      <xsl:when test="$default-pagemaster = 'body-odd'">
	<xsl:value-of select="'body-first-cms'"/>
      <xsl:when test="$default-pagemaster = 'body-even'">
	<xsl:value-of select="'body-first-cms'"/>
	<xsl:value-of select="$default-pagemaster"/>

3. Customised the 'article' template to call my 'runing.side.mode' template:

  <xsl:template match="article">
    <xsl:variable name="id">
      <xsl:call-template name="object.id"/>

    <xsl:variable name="master-reference">
      <xsl:call-template name="select.pagemaster"/>

    <!-- The elided part here just copied and pasted from
         fo/component.xsl ... -->

      <!-- This is a new template to add side content -->
      <xsl:apply-templates select="." mode="running.side.mode">
	<xsl:with-param name="master-reference" select="$master-reference"/>

4. Added a 'running.side.mode' template, basically cut, pasted and edited from 'running.head.mode':

  <xsl:template match="*" mode="running.side.mode">
    <xsl:param name="master-reference" select="'unknown'"/>
    <xsl:param name="gentext-key" select="name(.)"/>

    <!-- remove -draft from reference -->
    <xsl:variable name="pageclass">
	<xsl:when test="contains($master-reference, '-draft')">
	  select="substring-before($master-reference, '-draft')"/>
	  <xsl:value-of select="$master-reference"/>
    <fo:static-content flow-name="xsl-region-end-first">
    <fo:static-content flow-name="xsl-region-end-odd">
    <fo:static-content flow-name="xsl-region-end-even">
    <fo:static-content flow-name="xsl-region-end-blank">

Of course, at some point, I will replace the word 'foo' there with the graphic I want in the outer margins.


Line numbered programlisting

Bob Stayton

>I'm trying to convert docbooks to PDF.

>Since I'm working on programming books, I'm specially interested in the
>programlisting linenumbering, any ideas of which processor (docbook to pdf)
>can do it ?


>I'm using Saxon 6.5.3 to process my docbook and turn it into a fo to later
>turn it into a pdf with fop.
>The problem I'm having is with programlisting, I want the lines numbered so
>I open the tag like this: <programlisting linenumbering="numbered"> but I
>don't get it numbered.

The DocBook XSL stylesheets can number lines in a programlisting. You will need to use either Saxon or Xalan as the XSLT processor.

You need two more things to get linenumbering working:

1. Set the stylesheet parameter use.extensions to 1, as described in: Sagehill

2. Add the DocBook Saxon extensions to your Java CLASSPATH, as described in: Sagehill

By the way, that reference to the Saxon line numbering extension on the saxon.sourceforge.net site is related to getting the line number of an element in the XML *source* file, not the output. It has nothing to do with the above extensions that were written by Norm Walsh for use with DocBook and Saxon.


Customizing xrefstyle

Bob Stayton

> I've just finished carefully reading the chapter in Stayton's
> book on `Cross-references,' but there's one thing I can't figure
> out how to do.
> When in my FO customization layer I set insert.xref.page.number
> to 1, I get the default style of page number cross-references,
> namely, the page number in square brackets, e.g., "[12]".
> What I'd prefer is that such page numbers occur in the
> xrefstyle="select: title pageabbrev" style, e.g., "(p. 12)".
> Since I'm using the 1.65.1 stylesheets but the DTD is only
> DocBook 4.2, I could achieve this by adding this attribute to
> every <xref> element:
>     <xref role='select: title pageabbrev'/>
> However, I'd prefer to have this style of page number reference
> be the default in my customization layer, so I don't have to add
> this attribute in a zillion places.
> I spent some time grepping around the stylesheets, but I couldn't
> figure out where the templates connect with the gentext templates
> for "pageabbrev".

As you realized, using xrefstyle is good for ad hoc changes to individual xrefs, but it would be tedious to use as a global change of style for all references.

The default style for xref rendering comes from the gentext templates, which are in common/en.xml for English language documents. In your case, you only want to change how the page citation is rendered. Fortunately, there is a single gentext template that handles that for all xrefs. It is the template whose name is 'page.citation' in the 'xref' context in en.xml:

<l:template name="page.citation" text=" [%p]"/>

If you put a new version of that gentext template in your customization, then you will get it as the new default style for page numbers.


Coloring links, PDF output

Bob Stayton

> While I convert to HTML, text embedded in the 'linkend' tags gets colored
> denoting a hyperlink.
> However for PDF, there is no coloring to indicate that the text is also a
> link.
> How can I add colors to the linkend tags for a PDF output.

There is an example in my book on coloring link text in PDF output: Sagehill You customize the 'xref.properties' attribute set.


PDF output toc customization

Bob Stayton

> I am trying to customize a .pdf TOC to have the word "Chapter" in front of
> numbered chapters. i.e. as on http://www.sagehill.net/docbookxsl/
> Chapter 1. Introduction
> How this book is organized
> Online resources
> Chapter 2. Getting Started
> Logging In
> Etc.
> Chapter 3. Etc.

Below is the toc.line template that I used in my book. You are welcome to use it.

<xsl:template name="toc.line">
  <xsl:variable name="id">
    <xsl:call-template name="object.id"/>

  <xsl:variable name="label">
    <xsl:apply-templates select="." mode="label.markup"/>

  <fo:block text-align-last="justify"
      <xsl:when test="local-name(.) = 'part'">
        <xsl:attribute name="font-weight">bold</xsl:attribute>
        <xsl:attribute name="font-family">Helvetica</xsl:attribute>
        <xsl:attribute name="font-size">16pt</xsl:attribute>
        <xsl:attribute name="space-before">10pt</xsl:attribute>
        <xsl:attribute name="space-after">10pt</xsl:attribute>
        <xsl:attribute name="text-align-last">left</xsl:attribute>
      <xsl:when test="local-name(.)='chapter'
                    or local-name(.)='appendix'
                    or local-name(.)='glossary'
                    or local-name(.)='index'
                    or local-name(.)='preface'">
        <xsl:attribute name="font-weight">bold</xsl:attribute>
        <xsl:attribute name="font-size">12pt</xsl:attribute>
        <xsl:attribute name="space-before">4pt</xsl:attribute>
        <xsl:attribute name="space-after">2pt</xsl:attribute>
    <fo:inline keep-with-next.within-line="always">
      <fo:basic-link internal-destination="{$id}">
   <xsl:when test="local-name(.) = 'part'">
     <xsl:call-template name="gentext">
       <xsl:with-param name="key" select="'Part'"/>
     <xsl:text> </xsl:text>
   <xsl:when test="local-name(.) = 'chapter'">
     <xsl:call-template name="gentext">
       <xsl:with-param name="key" select="'Chapter'"/>
     <xsl:text> </xsl:text>
   <xsl:when test="local-name(.) = 'appendix'">
     <xsl:call-template name="gentext">
       <xsl:with-param name="key" select="'Appendix'"/>
     <xsl:text> </xsl:text>
        <xsl:if test="$label != ''">
          <xsl:copy-of select="$label"/>
          <xsl:value-of select="$autotoc.label.separator"/>
        <xsl:apply-templates select="." mode="title.markup"/>
    <xsl:if test="local-name(.) != 'part'">
      <fo:inline keep-together.within-line="always">
        <xsl:text> </xsl:text>
        <fo:leader leader-pattern="dots"
        <xsl:text> </xsl:text>
        <fo:basic-link internal-destination="{$id}">
          <fo:page-number-citation ref-id="{$id}"/>


Hyphenation, manually

Jirka Kosek

> You are not supposed to do it manually: stylesheets or other preprocessors
> should be able to cope with the task. Our assumption was that 
> a user can implement a line breaking algorighm of whatever complexity
> by writing a separate preprocessor that would insert zero-width spaces 
> and soft hyphens to control the formatter. Now it seems that the interface
> is too low-level, and requires too much effort to leverage. 

Just for the case that someone is intersted. I implemented exatly this yesterday. The following customization layer for DocBook XSL stylesheets allows line-breaking at /, \ and . (dot) when they are emitted as monospaced text by stylesheet (this includes e.g. filenames, classnames, function names and other similar markup).

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


<xsl:template name="inline.monoseq">
   <xsl:param name="content">
   <fo:inline xsl:use-attribute-sets="monospace.properties">
     <xsl:if test="@dir">
       <xsl:attribute name="direction">
           <xsl:when test="@dir = 'ltr' or @dir = 'lro'">ltr</xsl:when>
     <xsl:apply-templates select="exsl:node-set($content)" 

<xsl:template match="text()" mode="hyphenate" priority="2">
   <xsl:call-template name="string.subst">
     <xsl:with-param name="string">
       <xsl:call-template name="string.subst">
         <xsl:with-param name="string">
           <xsl:call-template name="string.subst">
             <xsl:with-param name="string" select="."/>
             <xsl:with-param name="target" select="'.'"/>
             <xsl:with-param name="replacement" select="'.&#x200B;'"/>
         <xsl:with-param name="target" select="'\'"/>
         <xsl:with-param name="replacement" select="'\&#x200B;'"/>
     <xsl:with-param name="target" select="'/'"/>
     <xsl:with-param name="replacement" select="'/&#x200B;'"/>

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


Ednote: string.subst is a template delivered as part of docbook.


How do I increase the column width of the inside column in a header?

Bob Stayton

>> [How do I increase the column width of the inside column in a header?]

> You are in luck.  The latest version of the XSL stylesheets has a new
> parameter 'header.column.widths' that lets you set the width of the columns
> in the headers and footers.  You need to download version 1.65.0 of the XSL
> stylesheets, and then read this reference doc in the distribution:

> doc/fo/header.column.widths.html

I followed your suggestion & added the line

   <!-- need more space for inside margins -->
   <xsl:param name="header.column.widths" select="'9 0 1'"/>