Re: [xsl] Changing table output from horizontal to vertical

Subject: Re: [xsl] Changing table output from horizontal to vertical
From: "Mark" <mark@xxxxxxxxxxxx>
Date: Sun, 18 Sep 2011 14:57:07 -0700
In case anyone follows this in the archives:
My error was misunderstanding what position() returns and using 'div' instead of 'idiv'.


The fragment of code that works is:
<xsl:variable name="rowcount" select="((count(Item[@lang eq 'en']) + 2) idiv 3)"/>
<table class="motif" lang="en">
<xsl:for-each select="Item[@lang eq 'en'][position() &lt;=$rowcount]">
<xsl:variable name="row" select="position()"></xsl:variable>
<tr>
<xsl:apply-templates select="."/>
<xsl:apply-templates select="../Item[@lang eq 'en'][number($row) + $rowcount]"/>
<xsl:apply-templates select="../Item[@lang eq 'en'][number($row) + $rowcount + $rowcount]"/>
</tr>
</xsl:for-each>
</table>


-----Original Message----- From: Mark
Sent: Sunday, September 18, 2011 1:31 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Changing table output from horizontal to vertical


My first problem solved: the round() caused the extra row; did not realize I
had done that when I was trying to get rid of the decimal/integer problem.
Thus, my problem is specifying the entries for the second and third columns,
which I flat out do not understand. Can anyone point out my XPath error,
please? Or is it context? I have not a clue.

For the second column I tried many variation on the following with no
success (the full code is below):
<xsl:apply-templates select="../Item[@lang eq 'en'][position() +
$rowcount]"/>
Thanks,
Mark

-----Original Message----- From: Mark
Sent: Sunday, September 18, 2011 12:35 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Changing table output from horizontal to vertical


Hi Liam,
Thanks for the code. I have a few problems. I am using XSLT2. First, I could
not specify the variable as="xs:integer"; the processor complained about the
raw value being a decimal. Second, the code gives me 10 rows, not 9, because
I am rounding up: this means I will have unnecessary blank cells. I know
that changing the +2 to a +1 will stop that, but I did not know why the +2
was in the expression in the first place. The most important issue is that I
do not know how to specify the second and third columns. My code (which only
gives me the first column with 10, not 9, cells), looks like this:

<xsl:variable name="rowcount" select="round((count(Item[@lang eq 'en']) + 2)
div 3)"/>
        <table class="motif" lang="en">
          <xsl:for-each select="Item[@lang eq 'en'][position()
&lt;=$rowcount]">
            <tr>
              <xsl:apply-templates select="."/>
              <xsl:apply-templates select="../Item[@lang eq
'en'][position() + $rowcount]"/> <!-- Not working at all -->
              <xsl:apply-templates select="../Item[@lang eq
'en'][position() + $rowcount + $rowcount]"/> <!-- Not working at all -->
            </tr>
          </xsl:for-each>
        </table>
and the <Item> template:
<xsl:template match="Item">
  <td>
    <h4>
      <xsl:element name="a">
        <xsl:attribute name="href" select="@file"/>
        <xsl:value-of select="@concept"/>
      </xsl:element>
    </h4>
  </td>
</xsl:template>

Can you help clear this up for me?

-----Original Message----- From: Liam R E Quin
Sent: Sunday, September 18, 2011 10:16 AM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: Re: [xsl] Changing table output from horizontal to vertical


On Sun, 2011-09-18 at 09:50 -0700, Mark wrote:
Hi,
I am using an XSLT template to produce an XHTML table.


 Currently, the
stylesheet fills the table in a horizontal direction; I would like to fill
the table in a vertical direction.
Instead of thinking of filling a table, think of it as a mapping from
the input tree to the output grid... Each output tr will start with the
nth input item and then have the n + NRth item, then n + NR * 2, and so
on, where NR is the number of rows (rounded up to the nearest integer if
there's a partial row).

You can work out the total number of rows (I'd store it in an XSLT
variable for clarity) e.g. in the template for List you could do
<xsl:template match="List">
 <xsl:variable name="rowcount"
     select="(ncount(Item[@lang eq $langcode]) + 2) div 3"
     as="xs:integer" />
(if you are still in 1998 and XSLT 1, leave of the "as" attribute and
use = instead of eq)

 <!--* now you can map the Items to table cells. *-->
 <xsl:for-each
   select="Item[@lang eq $langcode][position() &lt;= $rowcount]">
   <xsl:apply-templates select="." />
 </xsl:for-each>
</xsl:template>

In this example $langcode is a global parameter to the stylesheet, but
to handle both languages make it a tunnel parameter, or in XSLT 1 make
it a literal parameter and add it as an argument to the List template,
or if List generates the tables, you could instead do,
 <xsl:for-each select="distinct-values(Item/@lang)">
   generate a table in here
 </xsl:for-each>
perhaps with an xsl:sort instruction in there :)

Liam

--
Liam Quin - XML Activity Lead, W3C, http://www.w3.org/People/Quin/
Pictures from old books: http://fromoldbooks.org/

Current Thread