- 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