table position in xsl-fo

Tables

1. Is it possible to specify absolute position of a table in xsl
2. Keeping table cell data on same page
3. Creating Empty Tables
4. Centered Tables
5. Center a table
6. Centre a table horizontally
7. Repeating table headers on new pages
8. How to make a table cell span two columns
9. Spanning columns
10. Splitting long words in table cells
11. Table summary at end of page
12. Align a block to the bottom of a table-cell
13. Tables in xsl-fo
14. Table borders in xsl-fo
15. Wrapping text in table cells
16. Avoid page breaks in a table
17. Stretch the table to the end of page
18. Decimal align
19. Breaking long strings in table cells
20. Managing table-footers across pages
21. table-row height attribute
22. Setting column widths
23. Right align table cell content
24. Will the text fit? Calculating the length of text
25. fo:table display center or right (align)
26. Table headers
27. proportional Table columns
28. Table, with specific height
29. Table frame at page boundry
30. Table cell overflow
31. Table with vertical text content

1.

Is it possible to specify absolute position of a table in xsl

Nikolai Grigoriev

Yes: <fo:table absolute-position="absolute" left="1in" top="2in">

2.

Keeping table cell data on same page

Nikolai Grigoriev


<fo:table-cell keep-together.within-page="always">
     ...
</fo:table-cell>
	

should keep your table cells from splitting on page boundaries.

3.

Creating Empty Tables

Nikolai Grigoriev

> 3. There is an amendment certificate within the frontmatter which is just
a
> simple table without any data in it (is filled in by hand by owner of
> manual). I cannot seem to get the row height to apply (keep getting
default
> height based on selected font)  if there is no data in the cells. Is there
> a way to force the row height to be applied?
<fo:table-row height="X"> 

is the right syntax for it. If it does not work, ask the supplier of your formatter.

4.

Centered Tables

Nikolai Grigoriev

> 4. I cant seem to find a way to centre tables. I can centre the text 
> within a table, but not the table itself. I have tried using the
text-align
> attribute on the surrounding fo:block element and also on the table
> element, but this does not work - Am I missing something?

There's no such option as to centre tables in XSL FO. What you can do instead is to specify start-indent and/or end-indent on the table, to offset it from the right/from the left. If your formatter supports expressions, you can express it this way:

<fo:table width="[X]" start-indent="(100% - [X]) div 2">

This should center your table.... but see the next question! Only that one can be used for an auto-width table

5.

Center a table

Eliot Kimber



> is there a way to have a table centered if the table does not take up
> the entire page? Some equiv to html <table align="center"> thanks!

Put the table in a block with text-align="center". This requires that you have a fixed width on the table.

To vertically center anything you need a block-container with display-align="center".

6.

Centre a table horizontally

Ken Holman



>My intension is to center
>the table horizontally. But the space-start.optimum or the
>space-start.minimum parameter doesn't have any effect. I can't put the table
>into a block-container, because I wan't to span the table over multiple
>pages. Any suggestions?

The way to centre a <table> is to put it in a <table-and-caption> and use text-align="center". A working example is below.

<table-and-caption text-align="center">
   <table border="solid" border-collapse="collapse" table-layout="fixed">
     <table-column column-width="2cm"/>
     <table-column column-width="2cm"/>
     <table-body>
       <table-row>
         <table-cell><block>a</block></table-cell>
         <table-cell><block>b</block></table-cell>
       </table-row>
     </table-body>
   </table>
</table-and-caption>

If you are dealing with a fixed width table, then there is another approach you could follow that is a bit cumbersome:

   <table border="solid" border-collapse="collapse" table-layout="fixed"
          start-indent="( 100% - 4cm ) div 2">
     <table-column column-width="2cm"/>
     <table-column column-width="2cm"/>
     <table-body start-indent="0pt">
       <table-row>
         <table-cell><block>a</block></table-cell>
         <table-cell><block>b</block></table-cell>
       </table-row>
     </table-body>
   </table>

... but you need to know the size of the table before-hand. See how I take the difference between the entire width (100%) and the table width (4cm) and divide that difference by 2 to get how much belongs on the left. The end-indent isn't needed because of the fixed table width.

Note that I had to "undo" the start-indent= at the table-body, otherwise inheritance would have applied that indent to every cell's content.

7.

Repeating table headers on new pages

David Tolpin



> Using XSL:FO I have a situation where table data from one PDF page overflows
> and carries over onto the next PDF page. The data actually writes into the
> same area as my static content header text.
> Since the data that overflows is in a table is there anyway to have the
> first row of the table, the table header that contains the column headers,
> be repeated at the beginning of the second page?

table headers are repeated on subsequent pages by default. The behaviour is controlled by attribute 'table-omit-header-at-break'.

8.

How to make a table cell span two columns

Joshua

Is there a way to make a fo:table-cell span 2 columns?

<fo:table-cell number-columns-spanned="2">

9.

Spanning columns

Max Froumentin


> Basically, I have a block which can span over two columns, but I don't
> want to leave one line in the first column and several lines in the next
> column or vice versa.

keep-together.within-column="always"

is probably what you want.

10.

Splitting long words in table cells

Srini

I use the following property within fo:block inside fo:table-cell. hyphenate="true" It splits the words and inserts a hyphen character.

11.

Table summary at end of page

Ken Holman



>I've 2 block-container inside my region-body. The first block-container is 
>a table with n-rows inside. The 2nd block is
>a summaryblock and should reside always on the bottom of the page, if 
>possible on the first page but only if there are
>not too many rows inside the first block. How can i do that.

You can put the second block into a footnote and introduce an empty block after your first block with an empty footnote citation inline and your second block into the footnote body.

Remember (and I sound like a broken record here) ... don't get hung up on the names of the constructs. These are layout constructs you can use to achieve the desired layout regardless of the source of the information being laid out. Even though you aren't working with footnotes, your comment "should reside always on the bottom of the page" should bring to mind that the footnote construct is a construct that performs this particular kind of layout.

Of course the caveat in this case is that if you also have footnotes then I think you are out of luck.

<page-sequence master-reference="frame">

<static-content flow-name="xsl-region-after">
   <block text-align="center"><page-number/></block>
</static-content>

<flow flow-name="frame-body" font-size="40pt">
   <block space-after="20pt">This is a test</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>
   <block>Blocks of the first group</block>

   <block>
     <footnote>
       <inline/>
       <footnote-body>
         <block>Blocks of the second group</block>
         <block>Blocks of the second group</block>
         <block>Blocks of the second group</block>
         <block>Blocks of the second group</block>
         <block>Blocks of the second group</block>
       </footnote-body>
     </footnote>
   </block>

</flow>

</page-sequence>

12.

Align a block to the bottom of a table-cell

Ken Holman



>1. How do I align a block to the bottom of a table-cell?

Use display-align="after" for the cell ... see the example below.

>2. I've noticed that some fonts are smaller than others. Maybe those
>smaller fonts have more space around them. I'd like to see the actual size
>of each glyph. My attempt to do this was to add an &lt;fo:inline> with
>'background-color' on each character.
>The glyph width seem to appear, but I wonder if the height is the actual
>glyph height or the glyph height + whatever amount of space XSL adds as
>default line-height? If so, is there a way to strip the extra space around
>the glyph?

Two steps: (1) - only turn on the border for the character (by using an inline), not for the block (2) - optionally use line-height="1" to remove any leading on the line, though the leading may be useful for separation since the inline has prevented the leading from having the background colour. I've added this to the example below as well.

   <table border="solid" border-collapse="collapse">
     <table-column column-width="5cm"/>
     <table-column column-width="5cm"/>
     <table-column column-width="1cm"/>
     <table-column column-width="1cm"/>
     <table-column column-width="1cm"/>
     <table-body>
       <table-cell border="solid">
         <block>
           This is a cell with a long sentence in it.
         </block>
       </table-cell>
       <table-cell display-align="after" border="solid">
         <block>
           This is short.
         </block>
       </table-cell>
       <table-cell border="solid">
         <block><inline background="cyan">X</inline></block>
       </table-cell>
       <table-cell border="solid">
         <block line-height="1"><inline 
	background="cyan">X</inline></block>
       </table-cell>
       <table-cell border="solid">
         <block background="cyan">X</block>
       </table-cell>
     </table-body>
   </table>

13.

Tables in xsl-fo

Jeni Tennison



> this is my whole input:
>
> <DESCRIPTION_TABLE>
>    <DESCRIPTION_ITEM col="0" row="0">
>     <LABEL>Verantwortlicher</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>    <DESCRIPTION_ITEM col="0" row="1">
>     <LABEL>Prozessziel</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>    <DESCRIPTION_ITEM col="0" row="2">
>     <LABEL>Messgrösse</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>    <DESCRIPTION_ITEM col="0" row="3">
>     <LABEL>Benötigte Informationen</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>    <DESCRIPTION_ITEM col="0" row="4">
>     <LABEL>Erzeugte Ergebnisse</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>    <DESCRIPTION_ITEM col="1" row="0">
>     <LABEL>Externe Vorschriften</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>    <DESCRIPTION_ITEM col="1" row="1">
>     <LABEL>Hinweise</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>    <DESCRIPTION_ITEM col="1" row="2">
>     <LABEL>Potenzial</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>    <DESCRIPTION_ITEM col="1" row="3">
>     <LABEL>Mitgeltende Unterlagen</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>    <DESCRIPTION_ITEM col="1" row="4">
>     <LABEL>Offene Fragen</LABEL>
>     <VALUE>Text</VALUE>
>    </DESCRIPTION_ITEM>
>   </DESCRIPTION_TABLE>

If your XML is organised like this (i.e. sorted so that the last cell in the table is the last DESCRIPTION_ITEM in the DESCRIPTION_TABLE), then it's not too difficult to get a count of the columns and rows, actually -- just look at col and row attributes on the last DESCRIPTION_ITEM within the DESCRIPTION_TABLE. The number of columns is:


  DESCRIPTION_TABLE/DESCRIPTION_ITEM[last()]/@col + 1

and the number of rows is:

  DESCRIPTION_TABLE/DESCRIPTION_ITEM[last()]/@row + 1

> i need to make a table with 2 cols and 5 rows but there is no FOR -
> loop in XSL, right, so i have to use a xsl:for-each , i guess... but
> how?
>
> output is a <fo:table>

Then it's *much* easier than you think. fo:table doesn't require you to group your cells into rows -- instead, you can use the starts-row property on those cells that start a row.

First, the DESCRIPTION_TABLE maps onto your fo:table:

<xsl:template match="DESCRIPTION_TABLE">
  <fo:table>
    <fo:table-body>
      ...
    </fo:table-body>
  </fo:table>
</xsl:template>

Then you iterate over the DESCRIPTION_ITEMs in order to create the cells. The DESCRIPTION_ITEMs need to be sorted by row, and by column within the row, as follows:

<xsl:template match="DESCRIPTION_TABLE">
  <fo:table>
    <fo:table-body>
      <xsl:for-each select="DESCRIPTION_ITEM">
        <xsl:sort select="@row" data-type="number" />
        <xsl:sort select="@col" data-type="number" />
        <fo:cell>
          ...
          <xsl:apply-templates />
        </fo:cell>
      </xsl:for-each>
    </fo:table-body>
  </fo:table>
</xsl:template>

and if the DESCRIPTION_ITEM starts a row (i.e. its column number is 0) then you add a 'starts-row' attribute with the value 'true':

<xsl:template match="DESCRIPTION_TABLE">
  <fo:table>
    <fo:table-body>
      <xsl:for-each select="DESCRIPTION_ITEM">
        <xsl:sort select="@row" data-type="number" />
        <xsl:sort select="@col" data-type="number" />
        <fo:cell>
          <xsl:if test="@col = 0">
            <xsl:attribute name="starts-row">true</xsl:attribute>
          </xsl:if>
          <xsl:apply-templates />
        </fo:cell>
      </xsl:for-each>
    </fo:table-body>
  </fo:table>
</xsl:template>

If you were having to group the cells into rows then it would be a bit more complicated -- you'd have to use a grouping method. It would also be trickier if you had missing cells.

14.

Table borders in xsl-fo

David Tolpin



> I have a question concerning the table border in XSL FO.
> I use AntennaHouse XSL Formatter and I get a table without borders. 
 

border on fo:table sets border on the table as a whole. To set cell borders, specify borders on table-cell elements.

you also have got to specify the border-color and style, e.g.:

border-color="black"
border-style="solid" 
border-width="0.2mm"

15.

Wrapping text in table cells

Ken Holman



>I have a problem with long text in some table cells,
>that long words overflow the cells...
>text in cells with some words are wraped, but in the case of
>one long word, this word overwrites the cell.
>
>could anyone help me or have any idea about this....?

According to 7.9.4 the initial value for hyphenate= is "false" ... try setting it to "true" to see if your formatter's hyphenation algorithm gives you acceptable results.

16.

Avoid page breaks in a table

Oleg Tkachenko



> How can I code a <fo:table-row> so it moves to the next page if it doesn't
> fit on the current page? As it works now it starts on the current page and
> continues onto the next one.

Use

<fo:table-row keep-together="always"...

This will keep the row on the same page

17.

Stretch the table to the end of page

Klaas Bals



> The problem I am having is that when I run out of
> information to put in the table, it stops there, and I can't find a way
> to make it go to the end of the page.  Is there a way to make a table go
> to then end of the page on the last page it is on?  *The cells are not
> equal in height.

This is not possible in XSL-FO right now. I have seen an alternative which might lead to the same visual result. You could create a background image that contains rectangles in grey and light grey, where each rectangle corresponds to a column. If you then place a table on that page with that background, you get the visual effect that the background of the columns are alternating grey and light grey. The background image of course has the same size for all pages, and if you don't specify borders on the table, you cat get what you want. Vertical borders are visually 'replaced' by the background image. The only limitation is that the horizontal borders can not be used to delimit the rows. This however could be replaced by setting the background color of the cells alternating for each row.

18.

Decimal align

Paul Grosso


>I have a table with two columns.  I'd like all of the values in the columns
>to align in the center of the cell, so all the decimals line up.
>
>ex.
>10.0
>100.0
>1000.0
>
>I would like the decimals to align in the center of the cell.
>
>Can you do this with XSL:FO?

Set text-align="." on all the relevant fo:table-cell's.

See the <string> value of text-align at W3C

19.

Breaking long strings in table cells

Ken Holman




>I have long non-word string values in a table that are 
> running off the page.
>Most of these values contain no spaces at all.
>I would like them to wrap to the next line in the same cell, without 
>inserting a hyphen or other character.

If you insert the zero-width space character (using &#x200b; or &#8203;) periodically through the string, then it will break at this character where necessary and any others where it is not necessary will not be seen.

I used this in very long URL strings, adding this character after every slash. Where it isn't needed it isn't seen and where there needs to be a break it happens right after the slash.

David Tolpin adds

Turn hyphenation off for that part of the text and don't use an FO processor that breaks line when it is not asked to.

20.

Managing table-footers across pages

W. Eliot Kimber

If you control the vertical size of the rows, then you can use the trick where you put the table footer in static content for the region-after and use markers to set and get the footer on a per table basis.

The key to this is realizing that the edge regions can overlap the body region--so you define your page so the overlap provides enough space for the table footer. On pages without tables, the overlap space is occupied by an empty block (or just use an absolutely-positioned block-container to position the "real" page footer content correctly.

If you cannot control the vertical size of the rows, then this approach will not work because you won't be able to position the footer relative to the table (or rather, the table relative to the footer) reliably.

You can use this technique to generate a "table continued on next page" sort of message, as long as you don't necessarily want that message to always be immediately below the bottom of the last row on the page.

21.

table-row height attribute

David Tolpin



> It appears that the XSL-FO spec delegates to 
> the CSS2 spec to define the semantics of height on rows.

Yes, it is true.


>
> If you want to limit the height of the cell content, you 
> must put it in an fo:block-container with an explicit height= (or 
> block-progression-dimension= value).

No, it is not so. block-container with block-progression-dimension is a workaround which may work in some cases, and will not in others (when the cell is neihboring another one with row-span!=1). The correct way to limit the height of a cell is to specify block-progression-dimension on the table-cell itself. The specification allows to do so by explicitely listing block-progression-dimension on fo:table-cell.

There is an error in the specification in that both height and block-progression-dimension are listed for table-cell. This makes no sense since height is mapped to block-progression-dimension in XSL FO.

XSL FO allows it and it is the right way to specify cells with fixed height.

22.

Setting column widths

Eliot Kimber



> Is is possible to have a xsl-fo compliant stylesheet with both
> dynamic rows and columns ?

FO defines "auto" layout which has the same semantics as HTML tables. That is, the user agent figures out how wide to make the columns based on whatever heuristic it chooses to apply.

You can also use a "fixed" layout that uses proportional column width calculation using the proportional-column-width() FO expression function.

Typically, you define a constant width for those columns that need to accomodate a narrow data value or need to accodate data of known size and use proportional for the rest, e.g.:

<fo:table layout="fixed" width="100%">
   <fo:table-column column-width="0.5in"/>
   <fo:table-column column-width="proportional-column-width(1)"/>
   <fo:table-column column-width="proportional-column-width(1)"/>
   <fo:table-column column-width="proportional-column-width(1)"/>
   <fo:table-column column-width="proportional-column-width(1)"/>

This defines a table of 5 columns, the first one being 1/2 inch wide, the rest each being 1/4 of the remaining width.

23.

Right align table cell content

Victor Vishnyakov


> 1.  I have an image inside of a table cell and I want to right align 
> it in the cell.  But I don't see any attributes for align other than 
> a vertical align? Here is my xslfo
> <fo:table-cell >
> <fo:block >
> <fo:external-graphic height="1.5in"" src="url(blah.jpg)" /> 
> </fo:block> </fo:table-cell>

Try

<fo:table-cell >
        <fo:block text-align="right"> 
        <!-- text-align="right" is used here
                for right alignment --!>
		<fo:external-graphic height="1.5in"" src="url(blah.jpg)" /> 
	</fo:block> 
</fo:table-cell>

24.

Will the text fit? Calculating the length of text

W. Eliot Kimber


>How to find out if a piece of text will fit in a table?

I've posted to the Innodata Isogen Web site a simple Saxon extension that lets you estimate the formatted length of a string. This lets you do this kind of simple copy fitting, such as making sure a list accomodates the longest term in a definition list.

See: Isogen website

You may have to register and create a user ID, for which I appologize--I have no influence on our marketing policies.


> So how i have to use it???

Here's the sample XSLT script that should have been in the package. You do need the jar file in your classpath but the real key is the "xmlns:inno_iso=" attribute below: this binds the namespace prefix for the extension functions to the Java class that implements the functions according to the Saxon 6.x extension API.

---- cut here ----
<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
      xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
      xmlns:fo="http://www.w3.org/1999/XSL/Format"
   xmlns:inno_iso="java:com.innodata_isogen.saxon.InnodataSaxonExtensions"
 >
<!--======================================
     Copyright (c) 2004 Innodata Isogen, All Rights Reserved

     This XSLT transform demonstrates teh use of the InnodataSaxonExtensions
     Java library. It may be used, copied, or modified without restriction.

     Run this style sheet using Saxon from the xslt directory like so:

       java com.icl.saxon.StyleSheet -cp
../build/inno_iso_saxon_extensions.jar;../lib/saxon.jar
rendered_text_width_test.xml rendered_text_width_test_fo.xsl > test.fo

     $Revision: 1.4 $
     ======================================-->

<xsl:param name="base-font-size" select="'12pt'"/> <xsl:param
name="base-font-family" select="'Times New Roman'"/>

<xsl:template match="/">
   <fo:root
       font-size="{$base-font-size}"
       font-family="{$base-font-family}"
       line-height="120%"
   >
     <xsl:call-template name="generate-layout-master-set"/>
   	<xsl:apply-templates/>
   </fo:root>
</xsl:template>

<xsl:template match="/*">
   <fo:page-sequence master-reference="basepage">
     <fo:static-content flow-name="xsl-region-after">
       <fo:block
           text-align="center"
       >
         <xsl:text>-</xsl:text>
         <fo:page-number/>
         <xsl:text>-</xsl:text>
       </fo:block>
     </fo:static-content>
     <fo:flow flow-name="xsl-region-body"
     >
       <xsl:apply-templates/>
     </fo:flow>
   </fo:page-sequence>
</xsl:template>

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

<xsl:template match="/*/title">
   <fo:block
       font-size="16pt"
       font-weight="bold"
       font-family="sans-serif"
       space-after="1.5em"
     ><xsl:apply-templates/>
   </fo:block>
</xsl:template>

<xsl:template match="section/title">
   <fo:block
       font-size="14pt"
       font-weight="bold"
       space-before="12pt"
       space-after="1em"
     ><xsl:apply-templates/>
   </fo:block>
</xsl:template>

<xsl:template match="deflist">
   <xsl:variable name="label_width">
     <xsl:call-template name="get-longest-item-length">
       <xsl:with-param name="items" select="dlitem/term"/>
       <xsl:with-param name="curr_width" select="0"/>
       <xsl:with-param name="font-family" select="'Times New Roman'"/>
       <xsl:with-param name="font-weight" select="'bold'"/>
       <xsl:with-param name="font-size" select="12"/>
     </xsl:call-template>
   </xsl:variable>
   <xsl:apply-templates select="title"/>
   <fo:list-block
       provisional-distance-between-starts="{$label_width}"
       provisional-label-separation="1pt"
   >
     <xsl:apply-templates select="dlitem"/>
   </fo:list-block>
</xsl:template>

<xsl:template match="dlitem">
   <fo:list-item
       space-before="6pt"
   >
     <xsl:apply-templates/>
   </fo:list-item>
</xsl:template>

<xsl:template match="dlitem/term">
   <fo:list-item-label end-indent="label-end()">
     <fo:block
         font-weight="bold"
       ><xsl:apply-templates/>
     </fo:block>
   </fo:list-item-label>
</xsl:template>

<xsl:template match="dlitem/definition">
   <fo:list-item-body start-indent="body-start()">
     <xsl:apply-templates/>
   </fo:list-item-body>
</xsl:template>

<xsl:template match="deflist/title">
   <fo:block
       space-before="6pt"
       font-weight="bold"
       keep-with-next="always"
     ><xsl:apply-templates/>
   </fo:block>
</xsl:template>


<xsl:template match="para">
   <fo:block
       space-before="6pt"
     ><xsl:apply-templates/>
   </fo:block>
</xsl:template>

<xsl:template match="font_list">
   <fo:block
     space-before="6pt"
     linefeed-treatment="preserve"
   >
     <xsl:value-of select="inno_iso:listJavaSystemFonts()"/>
   </fo:block>
</xsl:template>
<xsl:template match="show_text_length">
   <xsl:variable name="font-family">
     <xsl:choose>
       <xsl:when test="string(@font-family) != ''">
         <xsl:value-of select="@font-family"/>
       </xsl:when>
       <xsl:otherwise><xsl:value-of
select="$base-font-family"/></xsl:otherwise>
     </xsl:choose>
   </xsl:variable>
   <xsl:variable name="font-weight">
     <xsl:choose>
       <xsl:when test="string(@font-weight) != ''">
         <xsl:value-of select="@font-weight"/>
       </xsl:when>
       <xsl:otherwise>normal</xsl:otherwise>
     </xsl:choose>
   </xsl:variable>
   <xsl:variable name="font-size">
     <xsl:choose>
       <xsl:when test="string(@font-size) != ''">
         <xsl:value-of select="@font-size"/>
       </xsl:when>
       <xsl:otherwise><xsl:value-of
select="$base-font-size"/></xsl:otherwise>
     </xsl:choose>
   </xsl:variable>
   <xsl:variable name="text">
     <xsl:apply-templates mode="text-only"/>
   </xsl:variable>
   <fo:inline
       border-style="solid"
       border-color="blue"
       border-width="0.5pt"
       font-size="{$font-size}"
       font-family="{$font-family}"
       font-weight="{$font-weight}"
     ><xsl:apply-templates
   /></fo:inline>
   <xsl:text> rendered length=</xsl:text
   ><xsl:value-of
       select="inno_iso:renderedTextLength($text, $font-family,
$font-weight, $font-size)"
   /><xsl:text>pt, font used: </xsl:text>
   <xsl:value-of select="inno_iso:renderedTextFontName($font-family,
$font-weight, $font-size)"/>
</xsl:template>

<xsl:template match="point_scale">
   <xsl:call-template name="pica-ruler">
     <xsl:with-param name="picas" select="18"/>
   </xsl:call-template>
</xsl:template>

<xsl:template name="get-longest-item-length">
   <!-- Given a list of nodes, process each one in text-only mode and return
the width of the
        longest as determined by the renderedTextLength() extension
function.

        When calling for the first time, specify a non-zero value for the
curr_width
        parameter to establish a minimum length to be returned.
     -->
   <xsl:param name="items"/><!-- List of elements to process, e.g. 
option_item/option -->
   <xsl:param name="curr_width"/><!-- Longest width we have so far -->
   <xsl:param name="font-family"/>
   <xsl:param name="font-weight"/>
   <xsl:param name="font-size"/>
   <xsl:variable name="text">
     <xsl:apply-templates select="$items[1]" mode="text-only"/>
   </xsl:variable>
   <xsl:variable name="cand_width"
         select="inno_iso:renderedTextLength(string($text),
                                             'NokiaSans',
                                             'bold',
                                             $font-size)"
   />
   <xsl:choose>
     <xsl:when test="count($items) = 0">
       <xsl:value-of select="concat($curr_width, 'pt')"/>
     </xsl:when>
     <xsl:when test="$curr_width > $cand_width">
       <xsl:call-template name="get-longest-item-length">
         <xsl:with-param name="items" select="$items[position() > 1]"/>
         <xsl:with-param name="curr_width" select="$curr_width"/>
         <xsl:with-param name="font-family" select="$font-family"/>
         <xsl:with-param name="font-weight" select="$font-weight"/>
         <xsl:with-param name="font-size" select="$font-size"/>
       </xsl:call-template>
     </xsl:when>
     <xsl:otherwise>
       <xsl:call-template name="get-longest-item-length">
         <xsl:with-param name="items" select="$items[position() > 1]"/>
         <xsl:with-param name="curr_width" select="$cand_width"/>
         <xsl:with-param name="font-family" select="$font-family"/>
         <xsl:with-param name="font-weight" select="$font-weight"/>
         <xsl:with-param name="font-size" select="$font-size"/>
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
</xsl:template>


<xsl:template name="generate-layout-master-set">
   <fo:layout-master-set>
     <fo:simple-page-master master-name="basepage"
         page-height="11in"
         page-width="8.5in">
       <fo:region-body
         margin-left="1in"
         margin-right="1in"
         margin-top="1in"
         margin-bottom="1in"
       />
       <fo:region-after
           extent="0.75in"
       />
     </fo:simple-page-master>
   </fo:layout-master-set>
</xsl:template>

<xsl:template name="pica-ruler">
   <xsl:param name="picas" select="6"/>
   <fo:table
       table-layout="fixed"
   >
     <xsl:call-template name="pr-generate-table-columns">
       <xsl:with-param name="picas" select="$picas"/>
     </xsl:call-template>
     <fo:table-body
         margin-left="0pt"
         start-indent="0pt"
         font-size="6pt"
          line-height="100%"
       >
       <fo:table-row>
         <xsl:call-template name="pr-generate-top-row-cells">
           <xsl:with-param name="max-value" select="$picas * 12"/>
         </xsl:call-template>
       </fo:table-row>
       <fo:table-row height="0.5em">
         <xsl:call-template name="pr-generate-mid-row-cells">
           <xsl:with-param name="picas" select="$picas"/>
         </xsl:call-template>
       </fo:table-row>
       <fo:table-row height="0.5em">
         <xsl:call-template name="pr-generate-bottom-row-cells">
           <xsl:with-param name="picas" select="$picas"/>
         </xsl:call-template>
       </fo:table-row>
     </fo:table-body>
   </fo:table>
</xsl:template>

<xsl:template name="pr-generate-table-columns">
   <!-- Generate one pica's worth of table column specs -->
   <xsl:param name="picas" select="0"/>
   <xsl:choose>
     <xsl:when test="$picas &lt;= 0 or $picas = 'NaN'"/>
     <xsl:otherwise>
       <fo:table-column
           column-width="4pt"/>
       <fo:table-column
           column-width="4pt"/>
       <fo:table-column
           column-width="4pt"/>
       <xsl:call-template name="pr-generate-table-columns">
         <xsl:with-param name="picas" select="$picas - 1"/>
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
</xsl:template>

<xsl:template name="pr-generate-top-row-cells">
   <!-- Generate one pica's worth of table cells for the first row -->
   <xsl:param name="max-value" select="0"/>
   <xsl:param name="picas-rendered" select="0"/>
   <xsl:choose>
     <xsl:when test="$picas-rendered >= $max-value"/><!-- Need to handle 
case where picas is not a multiple of 3 -->
     <xsl:otherwise>
       <fo:table-cell
         number-columns-spanned="3"
       >
         <fo:block><xsl:value-of 
select="$picas-rendered"/></fo:block><!-- 3 divisions of 4 points each -->
       </fo:table-cell>
       <fo:table-cell
         number-columns-spanned="3"
       >
         <fo:block><xsl:value-of select="$picas-rendered + (4 * 
3)"/></fo:block><!-- 3 divisions of 4 points each -->
       </fo:table-cell>
       <fo:table-cell
         number-columns-spanned="3"
       >
         <fo:block><xsl:value-of select="$picas-rendered + ((4 * 3) * 
2)"/></fo:block><!-- 3 divisions of 4 points each -->
       </fo:table-cell>
       <xsl:call-template name="pr-generate-top-row-cells">
         <xsl:with-param name="picas-rendered" select="$picas-rendered + 
(4 * 3) * 3"/>
         <xsl:with-param name="max-value" select="$max-value"/>
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
</xsl:template>

<xsl:template name="pr-generate-mid-row-cells">
   <!-- Generate one pica's worth of table cells for the middle row -->
   <xsl:param name="picas" select="0"/>
   <xsl:choose>
     <xsl:when test="$picas &lt;= 0 or string($picas) = 'NaN'"/><!-- 
Need to handle case where picas is not a multiple of 3 -->
     <xsl:otherwise>
         <fo:table-cell
             number-columns-spanned="3"
             border-start-style="solid"
             border-start-width="0.5pt"
             border-start-color="blue">
           <fo:block>&#x200B;</fo:block>
         </fo:table-cell>
         <fo:table-cell
             number-columns-spanned="3"
             border-start-style="solid"
             border-start-width="0.5pt"
             border-start-color="blue">
           <fo:block>&#x200B;</fo:block>
         </fo:table-cell>
         <fo:table-cell
             number-columns-spanned="3"
             border-start-style="solid"
             border-start-width="0.5pt"
             border-start-color="blue">
           <fo:block>&#x200B;</fo:block>
         </fo:table-cell>
       <xsl:call-template name="pr-generate-mid-row-cells">
         <xsl:with-param name="picas" select="$picas - 3"/>
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
</xsl:template>


<xsl:template name="pr-generate-bottom-row-cells">
   <!-- Generate one pica's worth of table cells for the middle row -->
   <xsl:param name="picas" select="0"/>
   <xsl:choose>
     <xsl:when test="$picas &lt;= 0 or string($picas) = 'NaN'"/><!-- 
Need to handle case where picas is not a multiple of 3 -->
     <xsl:otherwise>
       <fo:table-cell
           border-start-style="solid"
           border-start-width="0.5pt"
           border-start-color="blue">
         <fo:block>&#x200B;</fo:block>
       </fo:table-cell>
       <fo:table-cell
           border-start-style="solid"
           border-start-width="0.5pt"
           border-start-color="blue">
         <fo:block>&#x200B;</fo:block>
       </fo:table-cell>
       <fo:table-cell
           border-start-style="solid"
           border-start-width="0.5pt"
           border-start-color="blue">
         <fo:block>&#x200B;</fo:block>
       </fo:table-cell>
       <fo:table-cell
           border-start-style="solid"
           border-start-width="0.5pt"
           border-start-color="blue">
         <fo:block>&#x200B;</fo:block>
       </fo:table-cell>
       <fo:table-cell
           border-start-style="solid"
           border-start-width="0.5pt"
           border-start-color="blue">
         <fo:block>&#x200B;</fo:block>
       </fo:table-cell>
       <fo:table-cell
           border-start-style="solid"
           border-start-width="0.5pt"
           border-start-color="blue">
         <fo:block>&#x200B;</fo:block>
       </fo:table-cell>
       <fo:table-cell
           border-start-style="solid"
           border-start-width="0.5pt"
           border-start-color="blue">
         <fo:block>&#x200B;</fo:block>
       </fo:table-cell>
       <fo:table-cell
           border-start-style="solid"
           border-start-width="0.5pt"
           border-start-color="blue">
         <fo:block>&#x200B;</fo:block>
       </fo:table-cell>
       <fo:table-cell
           border-start-style="solid"
           border-start-width="0.5pt"
           border-start-color="blue"
       >
         <fo:block>&#x200B;</fo:block>
       </fo:table-cell>
       <xsl:call-template name="pr-generate-bottom-row-cells">
         <xsl:with-param name="picas" select="$picas - 3"/>
       </xsl:call-template>
     </xsl:otherwise>
   </xsl:choose>
</xsl:template>

</xsl:stylesheet>
-- 

25.

fo:table display center or right (align)

Tokushige Kobayashi


> How can i display a fo:table center or right?

> <fo:table display-align="center">
> ...
> </fo:table>

> doesn't work...

You may use text-align property.

<fo:table-and-caption space-before="1em" text-align="right">

Please check the following samples: antennahouse.com

26.

Table headers

Michael Sulyaev


> I am looking into the possibility of having column headings
> at the top of tables on each page, for tables that span multiple
> pages. Or in other words, can you get the column headings of a
> table to repeat at the top of each page the table is printed on,
> without working out where the page breaks are or anything stupid
> like that?
  

The fo:table-header formatting object is used to contain the content of the table header. Normally it is repeated right after a page break or column break crosses the table body.

<fo:table>
 <fo:table-header>
  <fo:table-row>
   <fo:table-cell>
    <fo:block> this is a cell in table-header </fo:block>
   </fo:table-cell>
   <!-- more cells in this row -->
  </fo:table-row>
  <!-- more rows in table-header -->
 </fo:table-header>
 <fo:table-body>
  . . . . . . .

27.

proportional Table columns

Alexander Peshkov



>> I tried to center a table.
>> This seems not to work with a short table  using
>> the recommended procedure:
>> 
>> <fo:table width="100%">
>>   <fo:table-column column-width="proportional-column-width(1)"/>
>>   <fo:table-column/>
>>   <fo:table-column column-width="proportional-column-width(1)"/>

1. According to XSL-FO specification proportional-column-width() can be used only for table with fixed layout.

2. Main reason that you get unexpected result is width="100%" specified on the outer table. As recommended by CSS2 formatter first determines actual column widths and if resulting width is less then required (100% is your case) - distributes the rest of the space evenly among columns. In the second sample this leads to additional space in the second column thus breaking centering of "SHORT" table.

If you remove width="100%" from the outer table and specify table-layout="fixed" you'll get what you want. Please find attached modified version of your sample (I've removed some unnecessary stuff).

28.

Table, with specific height

Ken Holman



>I'm trying to generate a table with a specific height, but it doesn't
>seem to do what I want. Here's the XSL:
>...
>I can change the height to about anything, but it will not change the
>height!

The construct I usually use to allocate space in the block-progression direction is <block-container>. Using height= on <table-cell> or <table-row> also works.

     <flow flow-name="frame-body" xmlns:fo="http://www.w3.org/1999/XSL/Format">
       <fo:block>This is a test</fo:block>
<fo:table width="130mm" border="2pt solid red"
background-color="rgb-icc(0,0,153,cmyk,1,0.79,0,0)">
     <fo:table-body>
         <fo:table-row>
             <fo:table-cell>
               <fo:block-container height="25mm">
                 <fo:block font-family="verdana"
color="rgb-icc(255,255,255,cmyk,0,0,0,0)" font-size="31pt">
                         XX
                 </fo:block>
               </fo:block-container>
             </fo:table-cell>
         </fo:table-row>
     </fo:table-body>
</fo:table>
       <fo:block>This is a test</fo:block>
<fo:table width="130mm" border="2pt solid red"
background-color="rgb-icc(0,0,153,cmyk,1,0.79,0,0)">
     <fo:table-body>
         <fo:table-row>
             <fo:table-cell height="25mm">

                 <fo:block font-family="verdana"
color="rgb-icc(255,255,255,cmyk,0,0,0,0)" font-size="31pt">
                         XX
                 </fo:block>

             </fo:table-cell>
         </fo:table-row>
     </fo:table-body>
</fo:table>
       <fo:block>This is a test</fo:block>
<fo:table width="130mm" border="2pt solid red"
background-color="rgb-icc(0,0,153,cmyk,1,0.79,0,0)">
     <fo:table-body>
         <fo:table-row height="25mm">
             <fo:table-cell>
                 <fo:block font-family="verdana"
color="rgb-icc(255,255,255,cmyk,0,0,0,0)" font-size="31pt">
                         XX
                 </fo:block>
             </fo:table-cell>
         </fo:table-row>
     </fo:table-body>
</fo:table>
       <fo:block>This is a test</fo:block>
<fo:table width="130mm"  height="25mm" border="2pt solid red"
background-color="rgb-icc(0,0,153,cmyk,1,0.79,0,0)">
     <fo:table-body>
         <fo:table-row>
             <fo:table-cell>
                 <fo:block font-family="verdana"
color="rgb-icc(255,255,255,cmyk,0,0,0,0)" font-size="31pt">
                         XX
                 </fo:block>
             </fo:table-cell>
         </fo:table-row>
     </fo:table-body>
</fo:table>
       <fo:block>This is a test</fo:block>
<fo:table width="130mm"  block-progression-dimension="25mm" 
border="2pt solid red"
background-color="rgb-icc(0,0,153,cmyk,1,0.79,0,0)">
     <fo:table-body>
         <fo:table-row>
             <fo:table-cell>
                 <fo:block font-family="verdana"
color="rgb-icc(255,255,255,cmyk,0,0,0,0)" font-size="31pt">
                         XX
                 </fo:block>
             </fo:table-cell>
         </fo:table-row>
     </fo:table-body>
</fo:table>
       <fo:block>This is a test</fo:block>

Interestingly, I'm getting different background results from different formatters when using height on <table>, but they agree that the cell size is not the table size.

The XSL specification builds on the CSS2 specification but according to a note in 6.7.3 "The CSS2 specification explicitly does not specify what the behavior should be if there is a mismatch between an explicitly specified table block-progression-dimension and the block-progression-dimensions of the content." Probably why I'm seeing different results in different processors.

Section 6.7.3 does explicitly say that the height is based on the "block-progression-dimension" trait, which defaults to "auto", which means the height is "auto". Reading 7.14.1 it would seem that height= does not play into the table's height, yet I'm getting identical results when I replace height= with block-progression-dimension= so I'm not sure what is in play here. My guess is that a table's height is always the height of its content (though I don't see that in section 6.7.3).

29.

Table frame at page boundry

Ken Holman


>I'm trying to have a frame around a table, the table spans several pages.
>Unfortunately it looks like FO does not close the frame at the bottom and
>at the top of every intermediary page on which appears the table.
>
>How could one implement in FO the frame="box" attribute on a large
>fo:table so that, at page breaks, the frame be closed on the bottom and at
>the top of the page on which appears the unfinished table ?

Remember that all lengths have .conditionality, that the width of a table border is a length, and the default conditionality is "discard". What you are seeing is what would be expected.

Try setting the .conditionality property of your table border width to "retain" so that the border width isn't discarded at the end of a reference area.

30.

Table cell overflow

Jeremias Maerki


> I want to clip the contents of a cell, such that the cell dimensions
> remain fixed no matter how much text is dumped into it, with the
> overflow simply getting cut off.

> Looking at some posts that Google turns up from 2003, giving a table
> cell a height attribute and setting overflow="hidden" is supposed to
> accomplish this, but doesn't. There seems to be some indication that
> isn't implemented. Is that still the case? Or has the way this is
> supposed to work changed?  How do I clip a cell?

You don't, at least no directly. The overflow property doesn't apply to fo:table-cell directly since that FO doesn't generate a viewport, only a reference area. If you want to clip cell contents you put a block-container with the desired extents as a direct child of the cell and you set the overflow property there.

31.

Table with vertical text content

Ken Holman




>   I have a table with a lot of small columns (a dozen of columns with
> only numbers.)  I would like to write the titles of the column
> vertically (because even single words are too large for each column
> width.)
>
>   I tried reference-orientation="90", both on the fo:table-cell and its
> inner fo:block, but the text is still horizontal within the cell.

reference-orientation isn't supposed to work on table-cell because that construct is only used to group content, not to create any areas itself.

reference-orientation isn't supposed to work on block because that construct creates a normal area not a reference area.

You need to use a block-container to get what you want:

  <page-sequence master-reference="frame">
    <flow flow-name="frame-body" xmlns="http://www.w3.org/1999/XSL/Format">
      <block>This is a test</block>
      <table>
        <table-body>
          <table-cell><block>Hello</block></table-cell>
          <table-cell>
            <block-container reference-orientation="90">
              <block>Hello</block>
            </block-container>
          </table-cell>
          <table-cell><block>Hello</block></table-cell>
        </table-body>
      </table>
    </flow>
  </page-sequence>