- From: Tim Mooney <mooney@dogbert.cc.ndsu.NoDak.edu>
- Date: Wed, 6 Oct 2004 16:00:45 -0500 (CDT)
- To: www-xsl-fo@w3.org
[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 Wednesday, 6 October 2004 21:05:07 UTC