Re: Tables filling page
"Mike Haarman" <[email protected]> Wed, 26 Mar 2003 11:56:20 -0600
| Newsgroups | gmane.text.xml.xsl.general |
|---|---|
| Message-ID | <[email protected]> |
From: <[email protected]> > > > 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 submit this solution to the problem. It illustrates a technique carried forward from my days laying type. I've included the complete stylesheet to shed some light on one particular manner of using XSLT to introduce dynamism to FO generation. Mea culpa the attachments. The busywork with variables at start of the stylesheet is to demonstrate that the technique can be utilized with a degree of flexibility, including parameters passed from calling process. The solution can be improved directly by increasing the precision of $font.size.factor:
instance.xml
(text/xml, 96 B)
<?xml version="1.0" encoding="utf-8"?>
<xmlroot>
<report>
<table/>
</report>
</xmlroot>
page-table.xsl
(text/xml, 10.1 KB)
<?xml version="1.0" encoding="utf-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
xmlns:fo="http://www.w3.org/1999/XSL/Format">
<!-- parameterize page and line properties -->
<!-- line values -->
<!-- base.size and base.lead specified in units assumed pts -->
<xsl:variable name="base.size" select="6"/>
<xsl:variable name="base.lead" select="2"/>
<!-- constant ratio of of true size to named size -->
<!-- varies for any given font and decreases as font size increases -->
<!-- this is for FOP's default serif font @ 10 on 12 -->
<xsl:variable name="font.size.factor" select=".8"/>
<!-- font-size values constructed -->
<xsl:variable name="body.font.size" select="concat($base.size + 4, 'pt')"/>
<xsl:variable name="body.line.height" select="concat($base.size + 4 + $base.lead, 'pt')"/>
<!-- modified by the font factor -->
<!-- this is the divisor for calculating body.depth.rows -->
<xsl:variable name="body.lead" select="string($base.size * $font.size.factor + 4 + $base.lead)"/>
<!-- page values -->
<xsl:variable name="page.height" select="66"/>
<xsl:variable name="page.width" select="51"/>
<xsl:variable name="margin.top" select="6"/>
<xsl:variable name="margin.bottom" select="6"/>
<xsl:variable name="margin.left" select="6"/>
<xsl:variable name="margin.right" select="6"/>
<xsl:variable name="region.before.extent" select="6"/>
<xsl:variable name="region.after.extent" select="0"/>
<!-- calculate body depth by rows -->
<!-- passed as parameter to template repeatRows -->
<!-- creates bounds for table to fill region-body -->
<xsl:variable name="region.body.depth" select="$page.height - $margin.top - $margin.bottom - $region.before.extent - $region.after.extent"/>
<xsl:variable name="body.depth.rows" select="floor(($region.body.depth * 12) div $body.lead)"/>
<!-- 8.5 X 11 page w/ 1 inch margins -->
<xsl:attribute-set name="page.definition">
<xsl:attribute name="page-height">
<xsl:value-of select="concat($page.height, 'pc')"/>
</xsl:attribute>
<xsl:attribute name="page-width">
<xsl:value-of select="concat($page.width, 'pc')"/>
</xsl:attribute>
<xsl:attribute name="margin-top">
<xsl:value-of select="concat($margin.top, 'pc')"/>
</xsl:attribute>
<xsl:attribute name="margin-bottom">
<xsl:value-of select="concat($margin.bottom, 'pc')"/>
</xsl:attribute>
<xsl:attribute name="margin-left">
<xsl:value-of select="concat($margin.left, 'pc')"/>
</xsl:attribute>
<xsl:attribute name="margin-right">
<xsl:value-of select="concat($margin.right, 'pc')"/>
</xsl:attribute>
</xsl:attribute-set>
<xsl:attribute-set name="region.body.definition">
<xsl:attribute name="margin-top">
<xsl:value-of select="concat($region.before.extent, 'pc')"/>
</xsl:attribute>
<xsl:attribute name="margin-bottom">
<xsl:value-of select="concat($region.after.extent, 'pc')"/>
</xsl:attribute>
</xsl:attribute-set>
<!-- style properties -->
<xsl:attribute-set name="body.serif">
<xsl:attribute name="font-family">serif</xsl:attribute>
<xsl:attribute name="font-size">
<xsl:value-of select="$body.font.size"/>
</xsl:attribute>
<xsl:attribute name="line-height">
<xsl:value-of select="$body.line.height"/>
</xsl:attribute>
<xsl:attribute name="font-weight">normal</xsl:attribute>
<xsl:attribute name="font-style">normal</xsl:attribute>
<xsl:attribute name="text-align">start</xsl:attribute>
</xsl:attribute-set>
<!-- utility template -->
<!-- repeatRows template is passed a param rows=*number-of-rows-to-repeat* -->
<xsl:template name="repeatRows">
<xsl:param name="rows"/>
<xsl:choose>
<xsl:when test="$rows > 0">
<fo:table-row>
<fo:table-cell>
<fo:wrapper xsl:use-attribute-sets="body.serif">
<fo:block> </fo:block>
</fo:wrapper>
</fo:table-cell>
</fo:table-row>
<xsl:call-template name="repeatRows">
<xsl:with-param name="rows" select="$rows - 1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise/>
</xsl:choose>
</xsl:template>
<!-- root template -->
<xsl:template match="/xmlroot/report">
<fo:root xmlns:fo="http://www.w3.org/1999/XSL/Format">
<fo:layout-master-set>
<!-- first page of report -->
<fo:simple-page-master
master-name="first"
xsl:use-attribute-sets="page.definition">
<!-- gives working page of 39pc X 54pc -->
<!-- header takes 6pc, leaving 48pc for body flow -->
<xsl:element name="fo:region-before">
<xsl:attribute name="region-name">masthead</xsl:attribute>
<xsl:attribute name="extent">
<xsl:value-of select="concat($region.before.extent, 'pc')"/>
</xsl:attribute>
</xsl:element>
<fo:region-body xsl:use-attribute-sets="region.body.definition"/>
<xsl:element name="fo:region-after">
<xsl:attribute name="extent">
<xsl:value-of select="concat($region.after.extent, 'pc')"/>
</xsl:attribute>
</xsl:element>
</fo:simple-page-master>
<!-- rest of pages -->
<fo:simple-page-master
master-name="rest"
xsl:use-attribute-sets="page.definition">
<!-- gives working page of 39pc X 54pc -->
<!-- header takes 6pc, leaving 48pc for body flow -->
<xsl:element name="fo:region-before">
<xsl:attribute name="region-name">runninghead</xsl:attribute>
<xsl:attribute name="extent">
<xsl:value-of select="concat($region.before.extent, 'pc')"/>
</xsl:attribute>
</xsl:element>
<fo:region-body xsl:use-attribute-sets="region.body.definition"/>
<xsl:element name="fo:region-after">
<xsl:attribute name="extent">
<xsl:value-of select="concat($region.after.extent, 'pc')"/>
</xsl:attribute>
</xsl:element>
</fo:simple-page-master>
<!-- last of pages -->
<!-- top margin adjusted for smaller region-before -->
<fo:simple-page-master
master-name="last"
xsl:use-attribute-sets="page.definition">
<!-- gives working page of 39pc X 54pc -->
<!-- header takes 6pc, leaving 48pc for body flow -->
<xsl:element name="fo:region-before">
<xsl:attribute name="region-name">runninghead</xsl:attribute>
<xsl:attribute name="extent">
<xsl:value-of select="concat($region.before.extent, 'pc')"/>
</xsl:attribute>
</xsl:element>
<fo:region-body xsl:use-attribute-sets="region.body.definition"/>
<xsl:element name="fo:region-after">
<xsl:attribute name="extent">
<xsl:value-of select="concat($region.after.extent, 'pc')"/>
</xsl:attribute>
</xsl:element>
</fo:simple-page-master>
<fo:page-sequence-master master-name="report">
<fo:repeatable-page-master-alternatives
maximum-repeats="no-limit">
<fo:conditional-page-master-reference
master-reference="first"
page-position="first"
odd-or-even="any"
blank-or-not-blank="any"/>
<fo:conditional-page-master-reference
master-reference="rest"
page-position="rest"
odd-or-even="any"
blank-or-not-blank="any"/>
<fo:conditional-page-master-reference
master-reference="last"
page-position="last"
odd-or-even="any"
blank-or-not-blank="any"/>
</fo:repeatable-page-master-alternatives>
</fo:page-sequence-master>
</fo:layout-master-set>
<fo:page-sequence master-reference="report"
white-space-collapse="false"
initial-page-number="1">
<fo:flow flow-name="xsl-region-body">
<xsl:apply-templates select="table"/>
</fo:flow>
</fo:page-sequence>
</fo:root>
</xsl:template>
<xsl:template match="table">
<!-- fo:block span="all" -->
<fo:table table-layout="fixed">
<fo:table-column column-width="0.1pt"/>
<fo:table-column column-width="39pc - 0.1pt"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell/>
<fo:table-cell number-rows-spanned="{$body.depth.rows}"
border="1.5pt solid black">
<fo:wrapper xsl:use-attribute-sets="body.serif">
<!-- call your interesting table here -->
<xsl:call-template name="interesting.table"/>
</fo:wrapper>
</fo:table-cell>
</fo:table-row>
<xsl:call-template name="repeatRows">
<xsl:with-param name="rows" select="$body.depth.rows - 1"/>
</xsl:call-template>
</fo:table-body>
</fo:table>
<!-- /fo:block -->
</xsl:template>
<xsl:template name="interesting.table">
<fo:table table-layout="fixed">
<fo:table-column column-width="10pt"/>
<fo:table-column column-width="23pc"/>
<fo:table-column column-width="5pc"/>
<fo:table-column column-width="5pc"/>
<fo:table-column column-width="5pc"/>
<fo:table-body>
<fo:table-row>
<fo:table-cell/>
<fo:table-cell>
<fo:block>
<xsl:text>An interesting item</xsl:text>
</fo:block>
</fo:table-cell>
<fo:table-cell text-align="center">
<fo:block>
<xsl:text>2</xsl:text>
</fo:block>
</fo:table-cell>
<fo:table-cell text-align="center">
<fo:block>
<xsl:text>$12.95</xsl:text>
</fo:block>
</fo:table-cell>
<fo:table-cell text-align="center">
<fo:block>
<xsl:text>$25.90</xsl:text>
</fo:block>
</fo:table-cell>
</fo:table-row>
</fo:table-body>
</fo:table>
</xsl:template>
</xsl:stylesheet>