The stylesheets provide several attribute-sets and templates for controlling table styles at different levels in a table. Here is a summary of them, and each is further described in the following sections.
Table 30.2. Table styles for print output
Name | XSL element | Properties are applied to: |
---|---|---|
table.properties | attribute-set | The outer fo:block that wraps the table and its title. |
formal.title.properties | attribute-set | The fo:block containing the table title. Applies also to example, figure, and equation titles. |
informaltable.properties | attribute-set | The fo:block containing the informaltable. |
table.table.properties | attribute-set | The fo:table element, for both table and informaltable. |
tabstyle | template | Utility template that returns the value of the current table's tabstyle attribute from within any table element context. |
table.frame | template | The fo:table element, computing border properties. |
table.row.properties | template | Each fo:table-row element. |
table.cell.properties | template | Each fo:table-cell element. |
table.cell.block.properties | template | The fo:block element inside each fo:table-cell . |
Many publications define certain styles that are to be used for all tables within a publication. With DocBook XSL, you can define a set of table style names, each of which is associated with a particular table style. Then your authors can select which style to use by specifying the style name in a tabstyle
attribute on a given table. This system lets the designer control the overall styles for tables, and makes it easy for an author to select a style that suitable for a particular table. If necessary, the author can override certain features of a table style, depending on how the customization is written.
Use the table.properties
attribute-set to set styles for the fo:block
that contains a table
and its title (but not an informaltable
). By default, this attribute-set just uses the attributes from the formal.object.properties
attribute-set:
<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 name="keep-together.within-column">always</xsl:attribute> </xsl:attribute-set>
By setting any or all of these attributes in the table.properties
attribute-set, you override the values copied from formal.object.properties
. You can also add new properties. Whatever properties you use must be applicable to fo:block
elements. If they are inheritable, they will be inherited by all blocks in the table, including the table title. You can use the formal.title.properties
attribute-set to apply properties to just the number and title, although those properties will also be applied to example, figure, and equation titles.
Note in particular that the last attribute inherited from formal.object.properties
adds a keep to the table block. This keeps the table title with the table, but it also means the table will be forced to a new page if the whole table does not fit on the current page. That may be inappropriate for long tables that could start on the current page. For individual tables, you can use a processing instruction to allow a table to break, as described in the section “Keep-together processing instruction”. Or you can change the attribute value to auto
to turn off the keep for all tables, and use the PI in individual tables to keep them together. This change can be made in the table.properties
attribute-set. You do not have to worry about keeping a table's title together with the table, because the title block itself has a keep-with-next
property.
The following example adjusts the space-before and adds a background shading to all tables. Because the background-color property is on the block, it encompasses the table and its title.
<xsl:attribute-set name="table.properties"> <xsl:attribute name="space-before.optimum">12pt</xsl:attribute> <xsl:attribute name="background-color">#EEEEEE</xsl:attribute> </xsl:attribute-set>
If you want a property's value in this attribute-set to be dependent on a table's tabstyle
attribute, then you can make the value conditional using xsl:choose
. In the next example, when tabstyle="shaded"
the block containing the table and its title will have a background color.
<xsl:attribute-set name="table.properties">
<xsl:attribute name="background-color">
<xsl:choose>
<xsl:when test="@tabstyle='shaded'">#EEEEEE</xsl:when>
<xsl:otherwise>inherit</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:attribute-set>
Since the context in which table.properties
is applied is the table
element, the attribute can simply test for its @tabstyle
attribute value. The test is executed each time the attribute-set is applied.
If you use an informaltable
element (a table without a number and title), then you will find that the attributes in table.properties
do not apply. The informaltable.properties
attribute-set is used for informaltable
elements. So if you want a property to apply to both, you have to add the attribute to both attribute-sets. Or you can have one attribute-set use the other:
<xsl:attribute-set name="informaltable.properties" xsl:use-attribute-sets="table.properties"/>
Just as table.properties
uses all the attributes from formal.object.properties
attribute-set, so does informaltable.properties
use all the attributes from informal.object.properties
.
See the section “table.properties attribute-set” for tips on using these attribute-sets.
While the table.properties
attribute set can be used to add properties to the fo:block
containing a table, you can use the table.table.properties
attribute-set to add properties to the fo:table
element itself. Table-specific properties such as table-layout
or table-omit-header-at-break
must be applied this way. The default attributes in this set are used for managing borders:
<xsl:attribute-set name="table.table.properties"> <xsl:attribute name="border-before-width.conditionality">retain</xsl:attribute> <xsl:attribute name="border-collapse">collapse</xsl:attribute> </xsl:attribute-set>
If you want a property's value in this attribute-set to be dependent on a table's tabstyle
attribute, then you can make the value conditional using xsl:choose
. In the next example, when tabstyle="shaded"
the table will have a background color. It differs from the similar example in the section “table.properties attribute-set” in that the area behind a table's title is not shaded.
<xsl:attribute-set name="table.table.properties">
<xsl:attribute name="background-color">
<xsl:choose>
<xsl:when test="ancestor-or-self::table[1]/@tabstyle='shaded' or
ancestor-or-self::informaltable[1]/@tabstyle='shaded'">#EEEEEE</xsl:when>
<xsl:otherwise>inherit</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:attribute-set>
Since the context in which table.table.properties
is applied is the tgroup
element, the attribute must test for the @tabstyle
attribute on the ancestor table element. In the case of HTML markup tables (permitted in DocBook since version 4.3), the tgroup
element is not used so the test must include ancestor-or-self
. The test is executed each time the attribute-set is applied.
Properties such as background-color
that are are set on the fo:table
can be overridden in the table rows or cells by local attributes or processing instructions.
The tabstyle
named template is a utility template that can be used by any table element's template to determine the current tabstyle
attribute value. A table formatting property may be implemented at any of several levels in a table, such as at the table, row, or cell levels. Any table element template can call the tabstyle
template, which returns the value of the current table's tabstyle
attribute. Using such a utility template makes it easy for all levels to work with the same value.
If a table element (table
or informaltable
) does not have a tabstyle
attribute, the template also checks for a tgroupstyle
attribute on the tgroup
element. That attribute would only be needed if a table uses more than one tgroup
and they need different styles.
Generally a template handling a table element calls the tabstyle
template and saves the result in a variable. Then it can use the variable in an xsl:choose
statement to implement different properties at that level for different table styles. See Example 30.6, “Customized table.cell.properties” for an example of such usage. The tabstyle
template was added to the stylesheets starting with version 1.72.
The template named table.row.properties
applies properties to each fo:table-row
in a table. Note that this is a named template, not an attribute-set. By making it a template, it is easier to customize for multiple properties on each row. This template is called just after the fo:table-row
opening tag in the output. The template should output one or more xsl:attribute
elements, which are applied to the table row just opened. The template must not output anything else, or it will generate errors in the table processing.
By default, the template processes any dbfo
processing instructions for background color and adds that property to the current row. See the section “Row background color” for more information on that processing instruction.
The following is an example of a customization that applies a background color to alternating rows of a table when its tabstyle
attribute is set to striped
.
<xsl:template name="table.row.properties"> <xsl:variable name="tabstyle"> <xsl:call-template name="tabstyle"/> </xsl:variable> <xsl:variable name="bgcolor"> <xsl:call-template name="dbfo-attribute"> <xsl:with-param name="pis" select="processing-instruction('dbfo')"/> <xsl:with-param name="attribute" select="'bgcolor'"/> </xsl:call-template> </xsl:variable> <xsl:variable name="rownum"> <xsl:number from="tgroup" count="row"/> </xsl:variable> <xsl:choose> <xsl:when test="$bgcolor != ''"> <xsl:attribute name="background-color"> <xsl:value-of select="$bgcolor"/> </xsl:attribute> </xsl:when> <xsl:when test="$tabstyle = 'striped'"> <xsl:if test="$rownum mod 2 = 0"> <xsl:attribute name="background-color">#EEEEEE</xsl:attribute> </xsl:if> </xsl:when> </xsl:choose> </xsl:template>
The table.cell.properties
named template applies properties to each fo:table-cell
in a table. Note that this is a named template, not an attribute-set. By making it a template, it is easier to customize for multiple properties on each cell. This template is called just after the fo:table-cell
opening tag in the output. The template should output one or more xsl:attribute
elements, which are applied to the table cell just opened. The template must not output anything else, or it will generate errors in the table processing.
By default, the table.cell.properties
template outputs properties that are passed to it as template parameters. These parameters deliver the values of properties set on that DocBook entry
element, or properties that were inherited from one of its table ancestor elements. For a discussion of how table properties such as align
can be inherited, see the section “Cell alignment”. The following annotated example shows the first part of the template before any customization:
Example 30.5. Default table.cell.properties template
<xsl:template name="table.cell.properties"> <xsl:param name="bgcolor.pi" select="''"/> <xsl:param name="rowsep.inherit" select="1"/> <xsl:param name="colsep.inherit" select="1"/> <xsl:param name="valign.inherit" select="''"/> <xsl:param name="align.inherit" select="''"/> <xsl:param name="char.inherit" select="''"/> <xsl:if test="$bgcolor.pi != ''"> <xsl:attribute name="background-color"> <xsl:value-of select="$bgcolor.pi"/> </xsl:attribute> </xsl:if> <xsl:if test="$rowsep.inherit > 0"> <xsl:call-template name="border"> <xsl:with-param name="side" select="'bottom'"/> </xsl:call-template> </xsl:if> <xsl:if test="$colsep.inherit > 0 and $col < ancestor::tgroup/@cols"> <xsl:call-template name="border"> <xsl:with-param name="side" select="'right'"/> </xsl:call-template> </xsl:if> ...
The table.cell.properties
template provides the opportunity to customize how cell properties are added to the output. Instead of just outputting the inherited value, the template can use whatever logic you want. For example, you can check the table's tabstyle
attribute value, and output the properties that are appropriate for a given named table style.
The following example shows how you can customize background color for a table with a tabstyle="styleA"
attribute:
Example 30.6. Customized table.cell.properties
<xsl:template name="table.cell.properties"> <xsl:param name="bgcolor.pi" select="''"/> ... <xsl:variable name="tabstyle"> <xsl:call-template name="tabstyle"/> </xsl:variable> <xsl:variable name="bgcolor"> <xsl:choose> <xsl:when test="$tabstyle = 'styleA' and ancestor::thead">#BBBBBB</xsl:when> <xsl:when test="$tabstyle = 'styleA'">#DDDDDD</xsl:when> <xsl:when test="$bgcolor.pi != ''"> <xsl:value-of select="$bgcolor.pi"/> </xsl:when> </xsl:choose> </xsl:variable> <xsl:if test="$bgcolor != ''"> <xsl:attribute name="background-color"> <xsl:value-of select="$bgcolor"/> </xsl:attribute> </xsl:if> ...
Get the | |
Put the resolved color value into another variable. | |
Use color | |
Use color | |
If no | |
Finally output a |
Here is some useful information about using this template:
The context for the template call is the current entry
element.
You can use xsl:number
to get the current entry's position in the table. For example:
<xsl:variable name="rownumber"> <xsl:number count="row" from="tbody"/> </xsl:variable> <xsl:variable name="cellnumber"> <xsl:number count="entry" from="row"/> </xsl:variable>
The $rownumber
and $cellnumber
variables can be used in expressions to determine property values.
You can implement as many tabstyle
names as you need, and you can have them generate as many properties as you need.
Each property must be permitted on an fo:table-cell
. You can use font properties, and they will be inherited by any block elements in the cell.
You can decide if an inherited value should override a tabstyle
value, or vice versa.
The table.cell.block.properties
named template applies properties to the fo:block
that is inside each fo:table-cell
in the output of a table. Note that this is a named template, not an attribute-set. By making it a template, it is easier to customize for multiple properties.
This template is called just after the fo:block
opening tag that appears at the beginning of each fo:table-cell
in the output. The template should output one or more xsl:attribute
elements, which are applied to the block just opened.
This template is used mainly to set font properties on the content of table cells. This template, because its output block is nested inside the fo:table-cell
, will override any properties set by the table.cell.properties
template.
By default, the table.cell.block.properties
template just makes table header cells bold. The following is the template before any customization:
<xsl:template name="table.cell.block.properties"> <xsl:if test="ancestor::thead"> <xsl:attribute name="font-weight">bold</xsl:attribute> </xsl:if> </xsl:template>
See the section “table.cell.properties template” for details of how to customize setting properties in table cells.
The default behavior for the print stylesheet is to try to keep each table together on a page. For short tables, this is usually desirable. But for larger tables, it can lead to awkward page breaks that leave large empty spaces on a page.
You can control how tables break across pages in the following ways:
You can turn on or off the keep-together
property for all tables by changing the property value in the table.properties
and informaltable.properties
attribute-sets. See the section “table.properties attribute-set” for more information.
For individual tables, you can use a processing instruction to control the keep-together
property. See the section “Keep-together processing instruction” for more information.
You can keep each row together by adding the keep-together
property to table.cell.properties
template. Since it is applied to each cell, it will as a side effect keep each row together. Vertically spanned cells will bring along cells in other rows.
Some tables are too wide to fit on a normal portrait page. Such tables may fit if the table is rotated 90 degrees and presented in landscape mode.
You can make a table print in landscape mode by putting a orient="land"
attribute on the table
or informaltable
element. That will rotate the table 90 degrees counter-clockwise, including any table title. This assumes your XSL-FO processor is capable of rotating the content of a fo:block-container
element. XEP, Antenna House, and Xml2PDF can, but the current FOP cannot.
Depending on the width of the table content, you may also want to set the width of the table. You can use a processing instruction as described in the section “Table width”.
There is one pretty big caveat for a landscape table: it must have few enough rows to fit onto one page. The current XSL-FO standard does not support carrying over content in a block-container to more than one page. The last rows of your table will simply not appear in the printed output if you try.
There is a workaround for this problem, though. G. Ken Holman of Crane Softwrights Ltd. has published a method for creating multipage landscape tables in XSL-FO. His Page Sequence Master Interleave (PSMI) method uses two passes to rearrange the pages in an FO file. PSMI is described at http://www.cranesoftwrights.com/resources/psmi/index.htm.
The main stylesheet feature that is used to format table titles for print output is the formal.title.properties
attribute-set. The following is the default definition of the attribute-set:
<xsl:attribute-set name="formal.title.properties" use-attribute-sets="normal.para.spacing"> <xsl:attribute name="font-weight">bold</xsl:attribute> <xsl:attribute name="font-size"> <xsl:value-of select="$body.font.master * 1.2"/> <xsl:text>pt</xsl:text> </xsl:attribute> <xsl:attribute name="hyphenate">false</xsl:attribute> <xsl:attribute name="space-after.minimum">0.4em</xsl:attribute> <xsl:attribute name="space-after.optimum">0.6em</xsl:attribute> <xsl:attribute name="space-after.maximum">0.8em</xsl:attribute> </xsl:attribute-set>
That attribute-set is used for titles of tables, figures, examples, equations, blockquotes, and procedures. If you make a change to the attribute-set, then it will be reflected in the titles of all of those elements.
However, it is possible to make a property value conditional when setting an attribute. The following is a customization that centers table titles, but not any of the other titles. All other properties are left as they were:
<xsl:attribute-set name="formal.title.properties">
<xsl:attribute name="text-align">
<xsl:choose>
<xsl:when test="self::table">center</xsl:when>
<xsl:otherwise>left</xsl:otherwise>
</xsl:choose>
</xsl:attribute>
</xsl:attribute-set>
The body of the xsl:attribute
whose name is text-align
has an xsl:choose
statement that checks to see if the current element in context is a table
. If it is, then set the value of text-align
to center
. Otherwise, set it to left
. This works because the xsl:attribute
is evaluated each time it is referenced in the attribute-set
.
What if you want to print all your table titles without the number label such as Table 3.2
? There is no stylesheet parameter that will turn them off. In order to eliminate table numbers from the table titles, any “table of tables”, and any cross references to tables, the following customization is necessary. A similar customization could be used for figures, examples, or equations.
<xsl:param name="local.l10n.xml" select="document('')"/> <l:i18n xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0"> <l:l10n language="en"> <l:context name="title"> <l:template name="table" text="%t"/> </l:context> <l:context name="xref-number-and-title"> <l:template name="table" text="the table titled “%t”"/> </l:context> </l:l10n> </l:i18n> <xsl:template match="table" mode="label.markup"/>
The local.l10n.xml
parameter is used to alter the generated text. In this case, you are changing the gentext templates for the table
element in the contexts of title
and xref-number-and-title
, which are the contexts that all the formal objects use. The changes eliminate the use of the word Table
and the %n
placeholder that generates the number. You can reword the cross reference text any way you like. Repeat the process for all the languages you are using.
The last line of the customization makes empty the template that matches on table
in mode label.markup
. That mode generates the number for an element. It is used in the table of contents when a table of tables is generated.
DocBook XSL: The Complete Guide - 4th Edition | PDF version available | Copyright © 2002-2007 Sagehill Enterprises |