Customizing PDF Output
Customizing PDF Output
Customizing PDF Output
WHITE PAPER
The default DITA Open Toolkit (DITA OT) provides XSL-FO stylesheets
that create simple, generic PDF files. The default DITA OT PDF output is a
good starting point, but it is an ugly place to stop.
To create better-looking PDF output with more publishing functions, you
David J. Kelly
Project Manager/ need to change XSL-FO stylesheets. What kinds of things can you do, and
Technical Consultant
where do you start? This paper explains how to modify XSL-FO stylesheets
in the DITA OT.
scriptorium
4
front-matter.xsl
front-matter_1.0.xsl
When a stylesheet file name ends with “_1.0,” this is an indication that it is used for processing
DITA content that is at version 1.1 or higher. In this example, the template to change is in the
front-matter_1.0.xsl file.
<xsl:otherwise>
<xsl:apply-templates select="$map/*[contains(@class, ' map/topicmeta ')]"/>
</xsl:otherwise>
</xsl:choose>
</fo:block>
</fo:block>
<!--<xsl:call-template name="createPreface"/>-->
</fo:flow>
</fo:page-sequence>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
The third line of this template (➊) indicates that if the version of DITA being used is 1.1 or
higher, use the template called createFrontMatter_1.0.
In the “otherwise” portion of the first choose statement (➋), the front matter section is created
with the fo:page-sequence element (➌). An xsl:call-template element (➍) invokes code that creates
the headers and footers for the front-matter page sequence. (“Updating headers and footers” on
page 6 describes how to modify headers and footers.)
The template creates an fo:flow element (➎) to tell the FO processor to flow the contents of topics
into the body area of the page. Then the template inserts an fo:block element (➏) containing the
contents of the front matter section. This fo:block references the __frontmatter attribute set, which is
contained in demo/fo/cfg/fo/attrs/front-matter-attr.xsl. The default version of this attribute set specifies
one style, which centers the alignment of the front matter. You can add any other attributes that
are valid for an fo:block, such as default fonts, borders, background colors, and so forth. For
example, here is the attribute set with alignment set to “left” and with an added “border” attribute
specifying a solid black, 4-point border (changes shown in bold):
<xsl:attribute-set name="__frontmatter">
<xsl:attribute name="text-align">left</xsl:attribute>
<xsl:attribute name="border">4pt solid black</xsl:attribute>
</xsl:attribute-set>
The next section of code (➐) contains an fo:block that creates the title on the title page. This block
refers to the __frontmatter__title attribute set, contained in front-matter-attr.xsl, which you can alter
with any attribute that is valid for an fo:block. This attribute set is where you change the font style
and size for the title, change the alignment, and change vertical placement using, for example, the
padding-top and the valign attributes.
Here is the attribute set modified with a larger font size, more line leading, and a serif font in
italics:
<xsl:attribute-set name="__frontmatter__title">
<xsl:attribute name="margin-top">80mm</xsl:attribute>
<xsl:attribute name="font-family">Garamond</xsl:attribute>
<xsl:attribute name="font-size">36pt</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="font-style">italic</xsl:attribute>
<xsl:attribute name="line-height">160%</xsl:attribute>
</xsl:attribute-set>
scriptorium
6
After the fo:block for the title is an xsl:choose statement (➑) that selects the text of the title from
one of the following (in order):
1. The bkinfo/title node, if available
2. The map element’s title attribute, if available
3. The first topic’s title element
If you need a different order of selection or a different location for the title text, change the code
in this section.
The line of code for the subtitle (➒) is outside the fo:block for the title, so its format falls under the
fo:block for the entire title page. If you want additional control over the subtitle, place it in its own
fo:block and apply formatting attributes to it. Here’s an example of line ➒ in which the subtitle is
placed in an fo:block with a new attribute set defined for it. The attribute set specifies right justi-
fication, 20-point Garamond regular text, and a red rule (using the block’s top border) between
the subtitle and the title. (This is an example to demonstrate XSL-FO, not an example to demon-
strate tasteful title page design!)
<fo:block use-attribute-sets="__frontmatter__subtitle">
<xsl:apply-templates select="//*[contains(@class,' bkinfo/bkinfo ')][1]/*[contains(@class,' bkinfo/bktitlealts
')]/*[contains(@class,' bkinfo/bksubtitle ')]"/>
</fo:block>
<xsl:attribute-set name="__frontmatter__subtitle">
<xsl:attribute name="margin-top">12pt</xsl:attribute>
<xsl:attribute name="font-family">Garamond</xsl:attribute>
<xsl:attribute name="font-size">20pt</xsl:attribute>
<xsl:attribute name="border-top">2pt solid red</xsl:attribute>
<xsl:attribute name="font-style">normal</xsl:attribute>
</xsl:attribute-set>
The new __frontmatter__subtitle attribute set should be placed in the front-matter-attr.xsl file for consis-
tency and future access.
After the subtitle, the template inserts another fo:block element (➓) containing the name of the
document owner. The contents of this block are selected from the bkinfo element, if it is available,
or from the map’s topicmeta element.
If you would like other items on the title page, insert them into the flow of XSL-FO objects
within the fo:block (➏)for the title page. Examples of additional content that commonly appear on
a title page include graphics and the publisher’s name.
With the attribute set, you can also create border rules or create a default font style for the text.
For example, if you want the header to be centered, in 12-point Eras bold type, and with a 1-point
rule along its bottom edge, the changed attribute set is as follows:
<xsl:attribute-set name="__toc__odd__header">
<xsl:attribute name="text-align">center</xsl:attribute>
<xsl:attribute name="margin-right">10pt</xsl:attribute>
<xsl:attribute name="margin-top">10pt</xsl:attribute>
<xsl:attribute name="border-bottom-width">1pt</xsl:attribute>
<xsl:attribute name="border-bottom-style">solid</xsl:attribute>
<xsl:attribute name="border-bottom-color">black</xsl:attribute>
<xsl:attribute name="font-family">Eras</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="font-size">12pt</xsl:attribute>
</xsl:attribute-set>
Going further down the header template, you see an xsl:call-template element (➌) that specifies the
remainder of the header’s content. Using this template, you can only specify the product name for
a predefined header template. You can change or replace the content within the xsl:call-template
element, or you can replace the entire element with XSL-FO structures of your own to get the
content and format in the header that you would like. Other programming constraints at this
point are that the XSL-FO element must be valid and well-formed within an fo:block element, and
any variables used must be active within this template.
In the body footer templates (called odd-footer and even-footer), content is placed in a table to
organize the text into different positions along the bottom of the page. One common change is to
alter these templates to add a third column in the middle to contain your company name or other
important information.
As you look through the other templates in static-content.xsl, you will see that similar approaches
apply to the other header and footer templates.
Handling fonts
Using fonts beyond the default fonts in the DITA OT requires configuring the DITA OT’s
instance of FOP (the FO processor that converts XSL-FO into PDF format). The process is docu-
mented on the Apache FOP website (http://xmlgraphics.apache.org/fop/0.95/configura-
tion.html) and further clarified in Scriptorium’s white paper, Configuring fonts in FOP and the
DITA Open Toolkit (http://www.scriptorium.com/whitepapers/fop_fonts/index.html). Please refer
to these resources for information about configuring fonts in the DITA OT.
Many of the attribute sets in the DITA OT reside in XSL files in the demo/fo/cfg/fo/attrs directory.
The names of the files give some indication as to what kinds of templates they contain, but in
some cases, the file naming is not easy to decipher. For example, the file that contains elements
used for highlighting text, such as <b> for bold and <i> for italics, is called hi-domain-attr.xsl.
The most direct way of finding an attribute set that affects a given DITA element is as follows:
1. Find an XSL template that selects the given attribute. For example, using a search tool that
enables you to find text in a group of files, look for section titles by searching for the following
string:
topic/title
This search returns a lot of results, but from it, you can find the template you are looking for.
The relevant result for this example is as follows:
<xsl:template match="*[contains(@class,' topic/section ')]/*[contains(@class,' topic/title ')]">
2. Examine the template and find a reference to an attribute set, if any. In the example for section
titles, the template includes the following lines:
<fo:block xsl:use-attribute-sets="section.title" id="{@id}">
<xsl:apply-templates/>
</fo:block>
The attribute set for section titles is named section.title.
3. When you find the attribute set name, search for it in the files. In most cases, the attribute set is
in the demo/fo/cfg/fo/attrs directory, but there may be exceptions.
4. When you find an attribute set, you can change, add, or delete attributes for the fo:block element
that the attribute set applies to. For example, here is the attribute set for section titles:
<xsl:attribute-set name="section.title">
<xsl:attribute name="font-family">Sans</xsl:attribute>
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="space-before.optimum">15pt</xsl:attribute>
<xsl:attribute name="keep-with-next.within-column">always</xsl:attribute>
</xsl:attribute-set>
The following example shows modifications that apply a 11-point regular Times Roman font
and 6 points of additional line spacing before the text:
<xsl:attribute-set name="section.title">
<xsl:attribute name="font-family">TimesRoman</xsl:attribute>
<xsl:attribute name="font-weight">regular</xsl:attribute>
<xsl:attribute name="space-before.optimum">11pt</xsl:attribute>
<xsl:attribute name="keep-with-next.within-column">always</xsl:attribute>
<xsl:attribute name="padding-before">6pt</xsl:attribute>
</xsl:attribute-set>
scriptorium
10
The function of attributes in a template is the same as the function of attributes in attribute sets.
(If one or more attributes can be used in different templates, the attributes should go in an attri-
bute set.)
Formatting may involve something other than an attribute. For example, you may want to format
a note as a one-row table with an icon in the left cell. An example of this usage already exists in the
DITA OT for notes, as follows:
<fo:table xsl:use-attribute-sets="note__table">
<fo:table-column column-number="1"/>
<fo:table-column column-number="2"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell xsl:use-attribute-sets="note__image__entry">
<fo:block>
➊ <fo:external-graphic src="url({concat($artworkPrefix, $noteImagePath)})" xsl:use-attribute-sets="image"/>
</fo:block>
</fo:table-cell>
<fo:table-cell xsl:use-attribute-sets="note__text__entry">
<xsl:call-template name="placeNoteContent"/>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
The template inserts the graphic into the note at ➊ within the context of a table that it creates for
the note. You might want the graphic to occur above the note text, in which case you could alter
the template to place the graphic in an fo:block preceding the note, as follows:
<fo:block>
<fo:external-graphic src="url({concat($artworkPrefix, $noteImagePath)})" xsl:use-attribute-sets="image"/>
</fo:block>
<xsl:call-template name="placeNoteContent"/>
Page size
Page margins are defined as global variables in the file demo/fo/cfg/fo/attrs/basic-settings.xsl.
You can modify the existing page size and page margin variables in this file, or you can create new
page size and page margin variables. (One reason for doing this is if different page sizes are
required for different parts of a book.)
Following is an example of the settings changed from US Letter page size (the DITA default) to
A4 page size:
<!-- The default of 215.9mm x 279.4mm is US Letter size (8.5x11in) -->
<xsl:variable name="page-width">210mm</xsl:variable>
<xsl:variable name="page-height">297mm</xsl:variable>
When you modify the existing variables, the changes affect fo:page-sequences whose fo:page-
sequence-master uses an fo:simple-page-master. The fo:simple-page-master references the page size and
page margin variables. For example, this snippet is from the createDefaultLayoutMasters template in
demo/fo/cfg/fo/layout-masters.xsl.
<fo:simple-page-master master-name="front-matter-first"
page-width="{$page-width}"
page-height="{$page-height}">
<fo:region-body margin-top="{$page-margin-top}"
margin-bottom="{$page-margin-bottom}"
margin-left="{$page-margin-left}"
margin-right="{$page-margin-right}"/>
</fo:simple-page-master>
If you create new page size variables, you can use these in new or existing fo:simple-page-master
elements. If you create new fo:simple-page-master elements, you then need to update or create
fo:page-sequence-master elements and fo:page-sequence elements to use the new settings.
Note that the page size and page margin variables in demo/fo/cfg/fo/attrs/basic-settings.xsl are set in
units of millimeters. The DITA OT supports a variety of units of length, including the following:
cm (centimeters)
mm (millimeters)
in (inches)
pt (points)
pc (picas)
px (pixels)
em (em-space length)
You can modify the lengths and units for all of the dimension variables. For example, change the
page-width and page-height to inches as follows:
<!-- The default of 215.9mm x 279.4mm is US Letter size (8.5x11in) -->
<xsl:variable name="page-width">8.5in</xsl:variable>
<xsl:variable name="page-height">11in</xsl:variable>
scriptorium
12
<!-- Change these if your page has different margins on different sides. -->
<xsl:variable name="page-margin-left" select="0.75in"/>
<xsl:variable name="page-margin-right" select="0.5in"/>
<xsl:variable name="page-margin-top" select="0.75in"/>
<xsl:variable name="page-margin-bottom" select="1in"/>
Notice in this example that the page-margin-left variable and related variables are set to absolute val-
ues. In the default format, they are all set to the value of the page-margins variable, so they are all
the same.
The problem with asymmetrical margins is that the values are used as “left” and “right” measure-
ments, not “inner” and “outer” measurements, which is what you might prefer for page margins.
One way to handle this is shown in the following example for the fo:simple-page-master on the even-
side, front-matter page (in the createDefaultLayoutMasters template in demo/fo/cfg/fo/layout-masters.xsl):
<fo:simple-page-master master-name="front-matter-even"
page-width="{$page-width}"
page-height="{$page-height}">
<fo:region-body margin-top="{$page-margin-top}"
margin-bottom="{$page-margin-bottom}"
margin-left="{$page-margin-right}"
margin-right="{$page-margin-left}"/>
<fo:region-before extent="{$page-margin-top}"
display-align="before"
region-name="even-frontmatter-header"/>
<fo:region-after extent="{$page-margin-bottom}"
display-align="after"
region-name="even-frontmatter-footer"/>
</fo:simple-page-master>
The page-margin-right variable is now used for the left margin, and the page-margin-left variable is
used for the right margin.
If this arrangement makes you semantically uncomfortable, you can also create your own page-
margin-inner and page-margin-outer variables and substitute them for the margin-left and margin-right
attributes in the fo:region-body elements where needed.
Number of columns
To change the number of columns on a page, you create new fo:simple-page-master elements in the
fo:layout-masters element and then you create a new fo:page-sequence-master that uses the fo:simple-
page-master elements. In the structure of the book, you create a condition that makes a new
fo:page-sequence that uses the specific fo:page-sequence-master defined with the required number of
columns. You can only specify the number of columns in a page layout for an fo:page-sequence.
This element can occur only at the top level of the fo:root element for the document. This level
corresponds to large document sections such as chapters, appendixes, the index, and so forth. You
cannot specify the number of columns at a lower level in the document without significant
restructuring of the XSL-FO for document organization.
Following is a short example of the technique for applying multiple columns to a document
section.
In this example, you change the number of columns in the createDefaultLayoutMasters template in
demo/fo/cfg/fo/layout-masters.xsl. Inside the fo:layout-master-set element, create the following fo:simple-
page-master. (Bold type indicates where this template is changed from the fo:simple-page-master
called body-first.)
<fo:simple-page-master
master-name="double-column"
page-width="{$page-width}"
page-height="{$page-height}">
➊ <fo:region-body
column-count="2"
column-gap="24pt"margin-top="{$page-margin-top}"
margin-bottom="{$page-margin-bottom}"
margin-left="{$page-margin-left}"
margin-right="{$page-margin-right}"/>
<fo:region-before extent="{$page-margin-top}"
display-align="before"
region-name="first-body-header"/>
<fo:region-after extent="{$page-margin-bottom}"
display-align="after"
region-name="first-body-footer"/>
</fo:simple-page-master>
You will find the controls for columns in the column-count and column-gap attributes on the
fo:region-body element (➊). Set the attribute values as needed for your application.
Also within the fo:simple-page-master in the same file, create the fo:page-sequence-master for double-
column pages, as follows:
<fo:page-sequence-master master-name="two-column">
<fo:repeatable-page-master-alternatives>
<fo:conditional-page-master-reference master-reference="double-column" odd-or-even="odd"
page-position="first"/>
<fo:conditional-page-master-reference master-reference="double-column" odd-or-even="odd"/>
<fo:conditional-page-master-reference master-reference="double-column" odd-or-even="even"/>
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>
scriptorium
14
This example uses the same fo:simple-page-master for all the pages. You could create different
fo:simple-page-masters for odd and even pages.
At this point, you can also apply the double-page layout to a specific chapter. To do this, you need
to specify which chapter should use the two-page column layout. The complete details of this
technique are beyond the scope of this paper.
For the sake of simplicity, the following example applies the two-column layout to all chapter
pages. In the processTopicChapter template in demo/fo/xsl/fo/commons.xsl, the first line in the template
is as follows:
<fo:page-sequence master-reference="body-sequence" xsl:use-attribute-sets="__force__page__count">
Change this line as follows:
<fo:page-sequence master-reference="two-column" xsl:use-attribute-sets="__force__page__count">
The master-reference attribute now applies the fo:pages-sequence-master with master-name="two-
column" to the text for all of the chapters.
Text indentation
Text indentation is controlled in a number of templates in the Idiom plugin. The best way to find
all instances of text indentation is to search for the following string in all the files in the demo/fo
directory:
<xsl:attribute name="margin-left">
The search results return several instances in the demo/fo/cfg/fo/attrs/commons-attr.xsl file, as well as
other files. For example, the margin-left attribute appears in the following attribute set for the
body text of a top-level topic:
<xsl:attribute-set name="body__toplevel">
<xsl:attribute name="margin-left">25pt</xsl:attribute>
<xsl:attribute name="font-size"><xsl:value-of select="$default-font-size"/></xsl:attribute>
</xsl:attribute-set>
You could set the text indentation by changing the value of the margin-left attribute in each loca-
tion, such as this one. This approach allows you to create different indents for each type of text
that is associated with a given attribute set.
Alternatively, you could use a variable that is already set up in the Idiom plugin and affect multiple
instances with a single value. In the demo/fo/cfg/fo/attrs/basic-settings.xsl file, find the following vari-
able definition:
<xsl:variable name="side-col-width">25pt</xsl:variable>
Currently, this variable is not actually used in the templates. To use this variable, modify all the
margin-left attributes in commons-attr.xsl and other files (that is, all the instances you want to change)
similar to the change shown in bold for the body__toplevel attribute set:
<xsl:attribute-set name="body__toplevel">
<xsl:attribute name="margin-left"><xsl:value-of select="$side-col-width"/></xsl:attribute>
<xsl:attribute name="font-size"><xsl:value-of select="$default-font-size"/></xsl:attribute>
</xsl:attribute-set>
Now you can change the value of the variable in the demo/fo/cfg/fo/attrs/basic-settings.xsl file and have
the new value reflected in multiple attribute sets.
You can also create additional variables in the basic-settings.xsl file if there are different groups of
elements that should receive similar indentation. For example, there is a set of indented, low-level
titles that you might want to have all at the same indentation, but at a different measurement than
the text indentation. Create a new variable in the demo/fo/cfg/fo/attrs/basic-settings.xsl file and use it
in the templates for the indented titles.
To create a new type of chapter (for instance, a chapter with a different column width), add a new
fo:page-sequence and associate a top-level topic to this fo:page-sequence using some kind of testing
or selection criteria. This selection or choice would need to take into account the selection pro-
vided by the topic template in demo/fo/xsl/fo/commons.xsl, which begins with the following line:
<xsl:template match="*[contains(@class, ' topic/topic ')]">
scriptorium
16
In this template, a variable invokes the determineTopicType template to determine what type of topic
is being processed. Topic types defined by the DITA OT include topicChapter, topicAppendix, topic-
Part, topicPreface, topicNotices, topicSimple, topicAbstract, and “otherwise.” Each topic type is processed
differently. Use this template to set up processing to define a different topic type or chapter type.
The top-level topic element is processed with the processTopicChapter template, which is as follows:
<xsl:template name="processTopicChapter">
➊ <fo:page-sequence master-reference="body-sequence" xsl:use-attribute-
sets="__force__page__count">
<xsl:call-template name="startPageNumbering"/>
<xsl:call-template name="insertBodyStaticContents"/>
➋ <fo:flow flow-name="xsl-region-body">
➌ <fo:block xsl:use-attribute-sets="topic">
<xsl:attribute name="id">
<xsl:value-of select="@id"/>
</xsl:attribute>
<xsl:if test="not(ancestor::*[contains(@class, ' topic/topic ')])">
<fo:marker marker-class-name="current-topic-number">
<xsl:number format="1"/>
</fo:marker>
<fo:marker marker-class-name="current-header">
<xsl:for-each select="child::*[contains(@class,' topic/title ')]">
<xsl:call-template name="getTitle"/>
</xsl:for-each>
</fo:marker>
</xsl:if>
<xsl:apply-templates select="*[contains(@class,' topic/prolog ')]"/>
➍ <xsl:call-template name="insertChapterFirstpageStaticContent">
<xsl:with-param name="type" select="'chapter'"/>
</xsl:call-template>
➎ <fo:block xsl:use-attribute-sets="topic.title">
<xsl:call-template name="pullPrologIndexTerms"/>
<xsl:for-each select="child::*[contains(@class,' topic/title ')]">
<xsl:call-template name="getTitle"/>
</xsl:for-each>
</fo:block>
➏ <xsl:call-template name="createMiniToc"/>
<xsl:apply-templates select="*[contains(@class,' topic/topic ')]"/>
</fo:block>
</fo:flow>
</fo:page-sequence>
</xsl:template>
The processTopicChapter template controls the chapter format setup, the chapter head static con-
tent, chapter-level TOC, and prolog. For some items, such as the chapter static content and
chapter-level TOC, additional templates are called. This is the template that creates the fo:page-
sequence for the chapter.
In the previous set of FO templates for the DITA OT, a single fo:page-sequence was used for the
entire book. The Idiom plugin now creates a new fo:page-sequence for each top-level topic.
For the fo:page-sequence (➊), the fo:flow (➋), and the top-level fo:block (➌) in the fo:flow element,
you can specify formatting characteristics that apply to the entire chapter. Some of these character-
istics include page numbering, default font settings, and so forth.
For example, the line after ➊ calls the startPageNumbering template. If you want the page number-
ing to start at 1 with the first page of the first chapter, go to the startPageNumbering template. There
you can take the code out of comments to restart the page numbering.
In the chapter head static content, which includes the word “Chapter” or “Part” and the chapter
or part number, the line at ➍ invokes the insertChapterFirspageStaticContent template. The chapter
title itself is placed inside the fo:block at line ➎, which derives its formatting from the topic.title
attribute set located in demo/fo/cfg/fo/attrs/common-attrs.xsl.
The “miniTOC,” or chapter-level table of contents, is created automatically when the chapter is
created. If you do not want a miniTOC to appear, or you want it to appear only when some con-
dition is met, you can control its insertion at line ➏. If you want to change the appearance or
functionality of the miniTOC, you modify it in the createMiniToc template, which is located fur-
ther down in the commons.xsl file.
Using the same source document, here is the table processed by the older, “legacy” FO stylesheets
in DITA OT 1.4.3:
scriptorium
20
...
</xsl:if>
<xsl:if test="number($colsep) and following-sibling::*[contains(@class, ' topic/entry ')]">
...
</xsl:if>
<xsl:if test="number($colsep) and not(following-sibling::*[contains(@class, ' topic/entry ')]) and
((count(preceding-sibling::*)+1) < ancestor::*[contains(@class, ' topic/tgroup ')][1]/@cols)">
...
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
In the xsl:call-template elements in this example, the processAttrSetReflection template hands off the
processing to attribute sets that specify the rule to use for the top, bottom, and right rules. You
could also place the attributes for creating rules directly in this template, or you could create your
own attribute sets with different values for the rules.
Table cells typically do not need this much indentation. For very dense tables the indent wastes a
lot of space. You can remove the indent by overriding the margin-left attribute inheritance in the
table cell.
The following example code shows the tbody.row.entry attribute set (located in demo/fo/cfg/fo/attrs/
tables-attr.xsl)
with a new entry. This entry specifies that the margin-left attribute value is 0pt.
<xsl:attribute-set name="tbody.row.entry">
<!--body cell-->
<xsl:attribute name="margin-left">0pt</xsl:attribute>
</xsl:attribute-set>
You also need to supply the margin-left attribute in the thead.row.entry attribute set to remove the
indent from the table header cells.
<xsl:attribute name="font-weight">bold</xsl:attribute>
<xsl:attribute name="text-align">center</xsl:attribute>
</xsl:attribute-set>
scriptorium
22
To control the border across the page margin, you use the “conditionality” property of lengths for
XSL-FO. The conditionality property applies to the top and bottom border, but specifying the
conditionality property for the border-bottom-width and border-top-width attributes does not work.
Change the attributes to border-before-width and border-after-width (changing the attributes for color
and style to match), and then add the conditionality property to the attributes. The modified attri-
bute set is as follows:
<xsl:attribute-set name="table__tableframe__all">
<xsl:attribute name="border-before-style">solid</xsl:attribute>
<xsl:attribute name="border-before-width">1pt</xsl:attribute>
<xsl:attribute name="border-before-width.conditionality">retain</xsl:attribute>
<xsl:attribute name="border-before-color">black</xsl:attribute>
<xsl:attribute name="border-after-style">solid</xsl:attribute>
<xsl:attribute name="border-after-width">1pt</xsl:attribute>
<xsl:attribute name="border-after-width.conditionality">retain</xsl:attribute>
<xsl:attribute name="border-after-color">black</xsl:attribute>
<xsl:attribute name="border-left-style">solid</xsl:attribute>
<xsl:attribute name="border-left-width">1pt</xsl:attribute>
<xsl:attribute name="border-left-color">black</xsl:attribute>
<xsl:attribute name="border-right-style">solid</xsl:attribute>
<xsl:attribute name="border-right-width">1pt</xsl:attribute>
<xsl:attribute name="border-right-color">black</xsl:attribute>
</xsl:attribute-set>
With these changes, the table border is completed at page breaks, as shown in the following
example:
Summary
This paper describes how to make basic changes to the format of PDF files produced by the
default DITA Open Toolkit. You can make numerous other changes to create PDF documents
that are more complex or visually satisfying. The DITA OT is capable of supporting a broad range
of output customizations, but understanding of XSL-FO and the DITA OT stylesheets does
require a bit of time and effort. The introduction provided by this paper is intended to help you
make some of your own customizations.
About Scriptorium
Scriptorium Publishing provides expert advice on how to develop, deploy, and manage content.
Our typical customer has thousands of pages of information, which needs to be delivered in print,
PDF files, HTML, and other media, often in dozens of languages. Our mission is to automate
formatting and production tasks, usually through XML technologies, so that authors can write
more efficiently.
Our consultants have experience in traditional publishing workflows, including typesetting, book
design, copyfitting, and production editing. This understanding influences our approach to creat-
ing state-of-the-art publishing systems with modern tools and technologies, such as XML,
HTML, DITA, the DITA Open Toolkit, XSLT, XSL-FO, FrameMaker, Ant, Perl, FrameScript,
Flash, InDesign, XMetaL, oXygen, and many more.
Our customers include federal and state government as well as companies in defense, consumer
electronics, telecommunications, health care, pharmaceutical, and other industries. If you are fac-
ing a difficult publishing challenge, we want to hear from you. Contact us at info@scripto-
rium.com or 919-481-2701 x105.
Scriptorium Publishing is based in the Research Triangle area of North Carolina and has been in
business since 1997.
scriptorium