1. | PDF output from Docbook | ||||
There are many options. For all of them you will need DocBook stylesheets available from Sourceforge
The list is not complete, but these are probably most commonly used ways to get PDF from DocBook source. | |||||
2. | How to insert a pagebreak into docbook output | ||||
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
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. | |||||
3. | Cross references to page numbers | ||||
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 | |||||
4. | XEP 2.7 (October 2001 Rec) and xsl-fo stylesheets | ||||
The master-name attribute on conditional-page-master-reference was renamed 'master-reference' sometime shortly before the REC was published. | |||||
5. | Running footer in article | ||||
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. | |||||
6. | Tables in fop | ||||
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). | |||||
7. | Handling long url's in pdf output | ||||
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 --> | |||||
8. | Custom Footers in XSL-FO | ||||
This information is current as of DocBook XSL Version 1.53.0
Generation of headers and footers is controlled by three templates each in
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:
| |||||
9. | Using pagemasters for n column output in XSL-FO output. | ||||
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:
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. | |||||
10. | Page numbers appear as ?? | ||||
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). | |||||
11. | Page break for images | ||||
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: <?jose-pagebreak?> 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'/>
</xsl:template>
| |||||
12. | Indentation in xsl-fo | ||||
Add <xsl:attribute name="text-indent">0.5in</xsl:attribute> or whatever indent you want. | |||||
13. | fo marker problem | ||||
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. | |||||
14. | fo to RTF using jfor, % units not working | ||||
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. | |||||
15. | appendix doesn't start a new page in XSL-FO output? | ||||
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. | |||||
16. | Creating boxed programlisting, xsl-fo output. | ||||
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"
use-attribute-sets="verbatim.properties">
<xsl:attribute name="font-family">
<xsl:value-of select="$monospace.font.family"/>
</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.master * 0.9"/>
<xsl:text>pt</xsl:text>
</xsl:attribute>
<xsl:attribute name="border-color">#0000FF</xsl:attribute>
<xsl:attribute name="border-style">solid</xsl:attribute>
<xsl:attribute name="border-width">heavy</xsl:attribute>
</xsl:attribute-set>
You can also add background color (<xsl:attribute name="background-color">#F0F0F0</xsl:attribute>) or any other attribute you want. | |||||
17. | Blank page layout | ||||
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. | |||||
18. | XEP with catalog support for fo output | ||||
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). | |||||
19. | Custom footer in fo output | ||||
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 | |||||
20. | Sidebar, in XSL-FO | ||||
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:attribute-set>
<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"
keep-with-next.within-column="always"
hyphenate="false">
<xsl:apply-templates select="./title"
mode="sidebar.title.mode"/>
</fo:block>
</xsl:if>
<xsl:apply-templates/>
<xsl:if test=".//footnote">
<fo:block font-family="{$body.font.family}"
font-size="{$footnote.font.size}"
keep-with-previous="always">
<xsl:apply-templates select=".//footnote"
mode="table.footnote.mode"/>
</fo:block>
</xsl:if>
</fo:block>
</fo:float>
</xsl:template>
<xsl:template match="sidebar//footnote">
<xsl:call-template name="format.footnote.mark">
<xsl:with-param name="mark">
<xsl:apply-templates select="." mode="footnote.number"/>
</xsl:with-param>
</xsl:call-template>
</xsl:template>
| |||||
21. | Breaking long lines in pdf 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')">
<fo:character
character=" "
font-size=".01pt"
treat-as-word-space="true"/>
</xsl:template>
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. | |||||
22. | revhistory not shown in pdf output | ||||
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 | |||||
23. | Pagebreaks in FO output | ||||
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'/>
</xsl:template>
Inside your XML documents you now add <?custom-pagebreak?> 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"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
version="1.0">
<xsl:import ref="/path/to/docbook-xsl/fo/docbook.xsl"/>
</xsl:stylesheet>
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. | |||||
24. | How can I set the Font size of <programlisting>s | ||||
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). | |||||
25. | Superscript font size in XSL-FO output | ||||
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">
disregard-shifts</xsl:attribute>
<fo:inline vertical-align="super" font-size="60%">
<xsl:copy-of select="$mark"/>
</fo:inline>
</xsl:template>
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. | |||||
26. | Titled figures, spacing | ||||
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> </xsl:attribute-set>
This can be done by using the formal.title.properties attribute set [2]. Here's a snippet from my customisation layer which
<xsl:attribute-set name="formal.title.properties"
use-attribute-sets="normal.para.spacing">
<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>
</xsl:attribute-set>
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. | |||||
27. | Cross references, how to modify layout | ||||
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"/> </l:context> 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. | |||||
28. | Image quality in PDF output | ||||
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.
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. | |||||
29. | Accentuate or indent wrapped lines | ||||
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:call-template>
</xsl:template>
<xsl:template name="lineblock">
<xsl:param name="text" select="''"/>
<xsl:choose>
<xsl:when test="contains($text, ' ')">
<fo:block wrap-option='wrap'
text-indent="-0.5in"
margin-left='0.5in'
white-space-collapse='false'
linefeed-treatment="preserve"
xsl:use-attribute-sets="monospace.properties">
<xsl:value-of select="substring-before($text, ' ')"/>
</fo:block>
<xsl:variable name="after"
select="substring-after($text, ' ')"/>
<xsl:choose>
<xsl:when test="contains($after, ' ')">
<xsl:call-template name="lineblock">
<xsl:with-param name="text" select="$after"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<fo:block wrap-option='wrap'
text-indent="-0.5in"
margin-left='0.5in'
white-space-collapse='false'
linefeed-treatment="preserve"
xsl:use-attribute-sets="monospace.properties">
<xsl:value-of select="$after"/>
</fo:block>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<fo:block wrap-option='wrap'
text-indent="-0.5in"
margin-left='0.5in'
white-space-collapse='false'
linefeed-treatment="preserve"
xsl:use-attribute-sets="monospace.properties">
<xsl:value-of select="$text"/>
</fo:block>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
The programlisting template calls the lineblock template. The lineblock template recursively parses the string value of the programlisting, looking for line ending characters " ". 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! | |||||
30. | Align tables by decimal content | ||||
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:table-cell>
<fo:block text-align="right">10</fo:block>
</fo:table-cell>
<fo:table-cell>
<fo:block text-align="left">.001%</fo:block>
</fo:table-cell>
| |||||
31. | Using greek characters with docbook and fop | ||||
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">Ο</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">
<xsl:apply-templates/>
</fo:inline>
</xsl:template>
Ugly, but works for me... | |||||
32. | Procedure Step Numbering | ||||
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"/>
</xsl:variable>
<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:choose>
<xsl:when test="count(../step) = 1 and 0 = 1">
<!--^^^^^^^^^-->
<xsl:text>•</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:apply-templates select="." mode="number">
<xsl:with-param name="recursive" select="0"/>
</xsl:apply-templates>.
</xsl:otherwise>
</xsl:choose>
</fo:block>
</fo:list-item-label>
<fo:list-item-body start-indent="body-start()">
<fo:block>
<xsl:apply-templates/>
</fo:block>
</fo:list-item-body>
</fo:list-item>
</xsl:template>
| |||||
33. | para customisation | ||||
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:apply-imports/>
</fo:block>
</xsl:template>
<xsl:template match="para">
<fo:block text-indent="1em">
<xsl:apply-imports/>
</fo:block>
</xsl:template>
| |||||
34. | Getting static content into region-start and end | ||||
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.)
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:repeatable-page-master-alternatives>
<fo:conditional-page-master-reference
master-reference="blank"
blank-or-not-blank="blank"/>
<fo:conditional-page-master-reference
master-reference="body-first-cms"
page-position="first"/>
<fo:conditional-page-master-reference
master-reference="body-odd-cms"
odd-or-even="odd"/>
<fo:conditional-page-master-reference
master-reference="body-even-cms"
odd-or-even="even"/>
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>
<fo:simple-page-master master-name="body-first-cms"
page-width="{$page.width}"
page-height="{$page.height}"
margin-top="{$page.margin.top}"
margin-bottom="{$page.margin.bottom}"
margin-left="{$margin.left.inner}"
margin-right="0pt">
<fo:region-body margin-bottom="{$body.margin.bottom}"
margin-top="{$body.margin.top}"
column-gap="{$column.gap.body}"
column-count="{$column.count.body}"
margin-right="{$page.margin.outer}">
</fo:region-body>
<fo:region-before region-name="xsl-region-before-first"
extent="{$region.before.extent}"
display-align="before"/>
<fo:region-after region-name="xsl-region-after-first"
extent="{$region.after.extent}"
display-align="after"/>
<fo:region-start region-name="xsl-region-start-first"
extent="0pt"/>
<fo:region-end region-name="xsl-region-end-first"
extent="{$page.margin.outer}"/>
</fo:simple-page-master>
<!-- 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:choose>
<xsl:when test="$default-pagemaster = 'body'">
<xsl:value-of select="'body-cms'"/>
</xsl:when>
<xsl:when test="$default-pagemaster = 'body-first'">
<xsl:value-of select="'body-first-cms'"/>
</xsl:when>
<xsl:when test="$default-pagemaster = 'body-odd'">
<xsl:value-of select="'body-first-cms'"/>
</xsl:when>
<xsl:when test="$default-pagemaster = 'body-even'">
<xsl:value-of select="'body-first-cms'"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$default-pagemaster"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
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>
<xsl:variable name="master-reference">
<xsl:call-template name="select.pagemaster"/>
</xsl:variable>
<!-- 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"/>
</xsl:apply-templates>
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:choose>
<xsl:when test="contains($master-reference, '-draft')">
<xsl:value-of
select="substring-before($master-reference, '-draft')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$master-reference"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<fo:static-content flow-name="xsl-region-end-first">
<fo:block>foo</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-end-odd">
<fo:block>foo</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-end-even">
<fo:block>foo</fo:block>
</fo:static-content>
<fo:static-content flow-name="xsl-region-end-blank">
<fo:block>foo</fo:block>
</fo:static-content>
</xsl:template>
Of course, at some point, I will replace the word 'foo' there with the graphic I want in the outer margins. | |||||
35. | Line numbered programlisting | ||||
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. | |||||
36. | Customizing xrefstyle | ||||
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. | |||||
37. | Coloring links, PDF output | ||||
There is an example in my book on coloring link text in PDF output: Sagehill You customize the 'xref.properties' attribute set. | |||||
38. | PDF output toc customization | ||||
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>
<xsl:variable name="label">
<xsl:apply-templates select="." mode="label.markup"/>
</xsl:variable>
<fo:block text-align-last="justify"
end-indent="{$toc.indent.width}pt"
last-line-end-indent="-{$toc.indent.width}pt">
<xsl:choose>
<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>
<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>
</xsl:when>
</xsl:choose>
<fo:inline keep-with-next.within-line="always">
<fo:basic-link internal-destination="{$id}">
<xsl:choose>
<xsl:when test="local-name(.) = 'part'">
<xsl:call-template name="gentext">
<xsl:with-param name="key" select="'Part'"/>
</xsl:call-template>
<xsl:text> </xsl:text>
</xsl:when>
<xsl:when test="local-name(.) = 'chapter'">
<xsl:call-template name="gentext">
<xsl:with-param name="key" select="'Chapter'"/>
</xsl:call-template>
<xsl:text> </xsl:text>
</xsl:when>
<xsl:when test="local-name(.) = 'appendix'">
<xsl:call-template name="gentext">
<xsl:with-param name="key" select="'Appendix'"/>
</xsl:call-template>
<xsl:text> </xsl:text>
</xsl:when>
</xsl:choose>
<xsl:if test="$label != ''">
<xsl:copy-of select="$label"/>
<xsl:value-of select="$autotoc.label.separator"/>
</xsl:if>
<xsl:apply-templates select="." mode="title.markup"/>
</fo:basic-link>
</fo:inline>
<xsl:if test="local-name(.) != 'part'">
<fo:inline keep-together.within-line="always">
<xsl:text> </xsl:text>
<fo:leader leader-pattern="dots"
leader-pattern-width="3pt"
leader-alignment="reference-area"
keep-with-next.within-line="always"/>
<xsl:text> </xsl:text>
<fo:basic-link internal-destination="{$id}">
<fo:page-number-citation ref-id="{$id}"/>
</fo:basic-link>
</fo:inline>
</xsl:if>
</fo:block>
</xsl:template>
| |||||
39. | Hyphenation, manually | ||||
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"
xmlns:fo="http://www.w3.org/1999/XSL/Format"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl"
exclude-result-prefixes="exsl"
version="1.0">
<xsl:import
href="http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl"/>
<xsl:template name="inline.monoseq">
<xsl:param name="content">
<xsl:apply-templates/>
</xsl:param>
<fo:inline xsl:use-attribute-sets="monospace.properties">
<xsl:if test="@dir">
<xsl:attribute name="direction">
<xsl:choose>
<xsl:when test="@dir = 'ltr' or @dir = 'lro'">ltr</xsl:when>
<xsl:otherwise>rtl</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:if>
<xsl:apply-templates select="exsl:node-set($content)"
mode="hyphenate"/>
</fo:inline>
</xsl:template>
<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="'.​'"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="target" select="'\'"/>
<xsl:with-param name="replacement" select="'\​'"/>
</xsl:call-template>
</xsl:with-param>
<xsl:with-param name="target" select="'/'"/>
<xsl:with-param name="replacement" select="'/​'"/>
</xsl:call-template>
</xsl:template>
<xsl:template match="node()|@*" mode="hyphenate">
<xsl:copy>
<xsl:apply-templates select="node()|@*" mode="hyphenate"/>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
Ednote: string.subst is a template delivered as part of docbook. | |||||
40. | How do I increase the column width of the inside column in a header? | ||||
I followed your suggestion & added the line <!-- need more space for inside margins --> <xsl:param name="header.column.widths" select="'9 0 1'"/> |