W3C home > Mailing lists > Public > www-xsl-fo@w3.org > October 2004

node after current node in xsl:for-each with xsl:sort (was: conditional page-break table based on row number?)

From: Tim Mooney <mooney@dogbert.cc.ndsu.NoDak.edu>
Date: Mon, 11 Oct 2004 15:03:23 -0500 (CDT)
To: www-xsl-fo@w3.org
Message-ID: <Pine.OSF.4.60.0410111337540.421768@dogbert.cc.ndsu.NoDak.edu>

In regard to: RE: conditional page-break table based on row number?, Roland...:

>> You can't do this:
>>
>> <fo:table-row {$breakvar} keep-together="always">
>
> I stand corrected. My example should have been:
> <fo:table-row break-before="{$breakvar}" keep-together="always">
> with appropriate value. David's code handles nulls better though.
>
> Cheers,
> Roland
>
>>
>> XSLT files have to be well formed XML.
>>
>> You can do
>>
>> <fo:table-row keep-together="always">
>>  <xsl:if test="position() mod 2 = 1">
>>  <xsl:attribute name="break-before">page</xsl:attribute>
>>  </xsl:if>

Thank you, David and Roland.  Your examples for multiple ways to approach
this problem really helped.  The usefulness of xsl:attribute had eluded me
when reading Doug Tidwell's "XSLT" book.

I'm still having a formatting problem with that same section of the
stylesheet, though.  I think it must be too many years of procedural
programming...

I want to do the stylesheet equivalent of this pseudo "code":

 	sorted_list_of_accounts = sort(/request/accounts)
 	foreach node in sorted_list_of_accounts
       if node mod 2 = 1
 		output <fo:table-row>

 		output <fo:table-cell>
 			output node/login
 			output node/password
 		output </fo:table-cell>

 		<!-- here's the part I don't know how to do -->
 		output <fo:table-cell>
 			output node+1/login
 			output node+1/password
 		output </fo:table-cell>

 		output </fo:table-row>
       end if
      end foreach

In other words, I iterate over a sorted list of accounts, and output two
accounts per table row.  Stripping out the page break logic from my
stylesheet, I've tried:

    <fo:table
         border="0.5pt solid black">

     <!-- our table has two columns, each of which uses half the body width -->
     <fo:table-column column-width="3.75in" />
     <fo:table-column column-width="3.75in" />

     <!-- no table headers, just start with the body -->
     <fo:table-body>

         <xsl:for-each select="/request/account">
         <xsl:sort select="./id" />

         <!-- output a table row if position() mod 2 = 1 -->
         <xsl:if test="position() mod 2 = 1">
             <fo:table-row keep-together="always">
                 <xsl:apply-templates select="." mode="cutsheet" />
                 <xsl:apply-templates
                             select="/request/account[position() + 1]"
                             mode="cutsheet" />
             </fo:table-row>
         </xsl:if>
         </xsl:for-each>

     </fo:table-body>
     </fo:table>


I've tried:

    <fo:table
         border="0.5pt solid black">

     <!-- our table has two columns, each of which uses half the body width -->
     <fo:table-column column-width="3.75in" />
     <fo:table-column column-width="3.75in" />

     <!-- no table headers, just start with the body -->
     <fo:table-body>

         <xsl:for-each select="/request/account">
         <xsl:sort select="./id" />

         <!-- output a table row if position() mod 2 = 1 -->
         <xsl:if test="position() mod 2 = 1">
             <fo:table-row keep-together="always">
                 <xsl:apply-templates select="." mode="cutsheet" />
                 <xsl:apply-templates
                             select="self::*[position() + 1]"
                             mode="cutsheet" />
             </fo:table-row>
         </xsl:if>
         </xsl:for-each>

     </fo:table-body>
     </fo:table>


and I've tried:


    <fo:table
         border="0.5pt solid black">

     <!-- our table has two columns, each of which uses half the body width -->
     <fo:table-column column-width="3.75in" />
     <fo:table-column column-width="3.75in" />

     <!-- no table headers, just start with the body -->
     <fo:table-body>

         <xsl:for-each select="/request/account">
         <xsl:sort select="./iid" />

         <!-- output a table row if position() mod 2 = 1 -->
         <xsl:if test="position() mod 2 = 1">
             <fo:table-row keep-together="always">
                 <xsl:apply-templates select="." mode="cutsheet" />
                 <xsl:apply-templates
                             select="following-sibling::.[1]"
                             mode="cutsheet" />
             </fo:table-row>
         </xsl:if>
         </xsl:for-each>

     </fo:table-body>
     </fo:table>


None of which works as I want, instead of

 	------------------------------------------
 	| Login: foo1      | Login: foo2         |
 	| Password: bar1   | Password: bar2      |
 	------------------------------------------
 	| Login: foo3      | Login: foo4         |
 	| Password: bar3   | Password: bar4      |
 	------------------------------------------

I get:

 	------------------------------------------
 	| Login: foo1      |                     |
 	| Password: bar1   |                     |
 	-------------------|                     |
 	| Login: foo3      |                     |
 	| Password: bar3   |                     |
 	------------------------------------------

It's clear that my logic to apply-templates to the "current node + 1"
doesn't work.

Am I even close, or am I going to need to implement something like the 
for loop template from the "XSLT" book?

Thanks,

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 Monday, 11 October 2004 20:03:25 GMT

This archive was generated by hypermail 2.2.0+W3C-0.50 : Wednesday, 3 October 2007 16:06:13 GMT