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

Subject: Re: [xsl] Changing table output from horizontal to vertical
From: Brandon Ibach <brandon.ibach@xxxxxxxxxxxxxxxxxxx>
Date: Sun, 18 Sep 2011 17:39:49 -0400
Mark,

Here's a complete version of a "List" template, which also handles
iterating through all the present languages, building a table for
each.

Keep in mind that using something like "position()" inside of a
[predicate] gives the position of the context node being filtered by
the predicate.  If you want to use the position of the node that is
current outside the XPath expression, you generally need to save it to
a variable, first, and use that inside the predicate, as shown here.

<xsl:template match="List">
	<xsl:for-each-group select="Item" group-by="@lang">
		<xsl:variable name="group" select="current-group()"/>
		<xsl:variable name="rowcount" select="ceiling(count($group) div 3)"/>
		<table class="motif" lang="{@lang}">
			<xsl:for-each select="$group[position() &lt;= $rowcount]">
				<xsl:variable name="pos" select="position() - 1"/>
				<tr>
					<xsl:apply-templates select="$group[(position() - 1) mod
$rowcount = $pos]"/>
				</tr>
			</xsl:for-each>
		</table>
	</xsl:for-each-group>
</xsl:template>

-Brandon :)


On Sun, Sep 18, 2011 at 4:31 PM, Mark <mark@xxxxxxxxxxxx> wrote:
> 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