- From: Roland Neilands <rneilands@pulsemining.com.au>
- Date: Fri, 8 Oct 2004 08:44:30 +1000
- To: "Tim Mooney" <mooney@dogbert.cc.ndsu.NoDak.edu>, <www-xsl-fo@w3.org>
Tim,
Two options:
1. Forget trying to insert the page break & let XSL-FO do it for you at the region-body margins. keep-together="always" works fine
on table rows in FOP.
2. XSL must be well formed XML. Set an XSL variable(*) for the page break attribute & use it in your table row instead.
eg:
<xsl:variable name="breakvar">
<xsl:choose>
<xsl:when test="position() mod 2 = 1">
<xsl:text>break-before="page"</xsl:text>
</xsl:when>
<xsl:otherwise>
<xsl:text></xsl:text>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
...
<fo:table-row {$breakvar} keep-together="always">
(*) - Not in the same sense as other programming languages. Be careful of scope.
http://www.zvon.org/xxl/XSLTutorial/Books/Output/example34_ch9.html
Regards,
Roland
> -----Original Message-----
> From: www-xsl-fo-request@w3.org [mailto:www-xsl-fo-request@w3.org]On
> Behalf Of Tim Mooney
> Sent: Thursday, 7 October 2004 7:01 AM
> To: www-xsl-fo@w3.org
> Subject: conditional page-break table based on row number?
>
>
>
> [I haven't yet subscribed to this list, please Cc: me on any replies]
>
> I have some XML data like:
>
> <?xml version="1.0"?>
> <request>
> <common>
> some common stuff, not important
> </common>
>
> <account>
> <id>foo1</id>
> <name>John. Q. Public</name>
> </account>
>
> <account>
> <id>foo2</id>
> <name>George Washington</name>
> </account>
>
> <!-- and so on, possibly hundreds of account elements -->
>
> </request>
>
> that I need to transform into PDF to look something like:
>
> -------------------------------------------------------------------------
> | Login ID: foo1 | Login ID: foo2 |
> | Customer Name: John Q. Public | Customer Name: George Washington |
> -------------------------------------------------------------------------
> | Login ID: foo3 | Login ID: foo4 |
> | Customer Name: John Adams | Customer Name: Thomas Jefferson |
> -------------------------------------------------------------------------
> | Login ID: foo5 | Login ID: foo6 |
> | Customer Name: Abraham Lincoln | Customer Name: Theodore Roosevelt|
> -------------------------------------------------------------------------
> | Login ID: foo7 | Login ID: foo8 |
> | Customer Name: Alexander Hamilton | Customer Name: Woodrow Wilson |
> -------------------------------------------------------------------------
> | Login ID: foo9 | Login ID: foo10 |
> | Customer Name: Herbert Hoover | Customer Name: John F. Kennedy |
> -------------------------------------------------------------------------
>
>
> The rub is that I can't have any of the cells broken by a page break --
> the page break must happen between rows in the table, not within a cell.
>
> I'm using Apache fop 0.20.5, which doesn't have support for most of the FO
> that one would use to control that -- widows, orphans, keep-togethers, etc.
>
> If I just mark up static content with FO, I can just do a
>
> <fo:table-row break-before="page">
>
> before every N rows, let's say every 20 rows. I have "perfect" output
> happening, with static content marked up and transformed to PDF via fop.
>
>
> The problem is that now I want to transform my XML data, and I'm having a
> miserable time trying to conditionally output the right fo:table-row.
>
> I want to do something like:
>
> <xsl:for-each select="/request/account">
> <xsl:sort select="./id" />
>
> <!-- output a table row if position() mod 2 = 1 -->
> <xsl:choose>
> <xsl:when test="position() mod 2 = 1">
> <!-- yes, should it be a normal fo:table-row or one with -->
> <!-- a page break? -->
> <xsl:choose>
> <xsl:when test="position() = 1">
> <!-- this will be the first cell, don't force a page break here -->
> <!-- just a normal page table row -->
> <fo:table-row keep-together.within-page="always">
> </xsl:when>
> <xsl:otherwise>
> <!-- have we output enough so we should force a break? -->
> <xsl:choose>
> <xsl:when test="position() mod 20 = 0">
> <!-- filled a page, output table-row and page-break -->
> <fo:table-row break-before="page"
> keep-together.within-page="always">
> </xsl:when>
> <xsl:otherwise>
> <!-- just a normal page table row -->
> <fo:table-row keep-together.within-page="always">
> </xsl:otherwise>
> </xsl:choose>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:when>
> </xsl:choose>
>
> <!-- now output a table cell -->
>
> <xsl:apply-templates select="." mode="cutsheet" />
>
> <!-- if postion() mode 2 = 0, we should output a row close, we've -->
> <!-- finished a row of 2 cells, and should output a /fo:table-row -->
> <xsl:if test="position() mod 2 = 0">
> </fo:table-row>
> </xsl:if>
> </xsl:for-each>
>
>
>
> The problem is that the xslt processor will choke on that, because it
> sees e.g.
>
> <xsl:if test="position() mod 2 = 0">
> </fo:table-row>
> </xsl:if>
>
> which is a mismatched tag.
>
>
>
>
> Next I tried:
>
>
> <xsl:for-each select="/request/account">
> <xsl:sort select="./iid" />
>
> <!-- output a table row if position() mod 2 = 1 -->
> <xsl:choose>
> <xsl:when test="position() mod 2 = 1">
> <!-- yes, should it be a normal fo:table-row or one with -->
> <!-- a page break? -->
> <xsl:choose>
> <xsl:when test="position() = 1">
> <!-- just a normal page table row -->
> <fo:table-row keep-together.within-page="always">
> <xsl:apply-templates select="." mode="cutsheet" />
> <xsl:apply-templates select="following-sibling::."
> mode="cutsheet" />
> </fo:table-row>
> </xsl:when>
> <xsl:otherwise>
> <!-- have we output enough so we should force a break? -->
> <xsl:choose>
> <xsl:when test="position() mod 28 = 0">
> <!-- filled a page, output table-row and page-break -->
> <fo:table-row break-before="page"
> keep-together.within-page="always">
> <xsl:apply-templates select="." mode="cutsheet" />
> <xsl:apply-templates select="following-sibling::."
> mode="cutsheet" />
> </fo:table-row>
> </xsl:when>
> <xsl:otherwise>
> <!-- just a normal page table row -->
> <fo:table-row keep-together.within-page="always">
> <xsl:apply-templates select="." mode="cutsheet" />
> <xsl:apply-templates select="following-sibling::."
> mode="cutsheet" />
> </fo:table-row>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:otherwise>
> </xsl:choose>
> </xsl:when>
> </xsl:choose>
> </xsl:for-each>
>
>
>
> In other words, don't just output a fo:table-row, output both the opening
> and closing tags for the row, and try get two cells in between them.
>
> As I expected, that doesn't work correctly either, I end up with:
>
> -------------------------------------------------------------------------
> | Login ID: foo1 | |
> | Customer Name: John Q. Public | |
> -------------------------------------| |
> | Login ID: foo3 | |
> | Customer Name: John Adams | |
> -------------------------------------| |
> | Login ID: foo5 | |
> | Customer Name: Abraham Lincoln | |
> -------------------------------------------------------------------------
>
>
> and so on.
>
> Can anyone suggest a way to accomplish what I'm trying to do? I'll gladly
> provide more info if I've left anything pertinent out.
>
> Tim
> --
> Tim Mooney mooney@dogbert.cc.ndsu.NoDak.edu
> Information Technology Services (701) 231-1076 (Voice)
> Room 242-J6, IACC Building (701) 231-8541 (Fax)
> North Dakota State University, Fargo, ND 58105-5164
>
>
>
Received on Thursday, 7 October 2004 22:46:36 UTC