There's an example showing how to do this on p343 of my book (4e). I think
it needs a two-phase solution:
<xsl:template match="towns">
<xsl:variable name="sorted-towns" as="element()*">
<xsl:perform-sort select="town">
<xsl:sort/>
</xsl:perform-sort>
</xsl:variable>
<table>
<xsl:for-each-group select="$sorted-towns"
group-by="position() mod (last() idiv $cols)">
<tr>
<xsl:for-each select="current-group()">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each-group>
</table>
</xsl:template>
Regards,
Michael Kay
http://www.saxonica.com/
http://twitter.com/michaelhkay
-----Original Message-----
From: Syd Bauman [mailto:Syd_Bauman(_at_)Brown(_dot_)edu]
Sent: 03 December 2009 03:17
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
Subject: [xsl] both sorting and grouping set of nodes
Warning: intended to be read in a monospaced typeface.
This may abe a FAQ, but if so, I didn't find it on D.
Pawson's FAQ pages.
The basic idea is that I want to extract a sizeable set of
nodes from a file, sort them, and spit out the output in a
4-column XHTML table.
So let's pretend I have an input document with a few hundred
<name> elements. And presume the content thereof is aready in
the desired format (e.g., "Surname, Forename" -- it's not,
but let's start with the easy case). I know how to spit out a
sorted list of them:
<ul>
<xsl:for-each select="//name">
<xsl:sort select="normalize-space(.)"/>
<li><xsl:value-of select="normalize-space(.)"/></li>
</xsl:for-each>
</ul>
Or, a bit more robustly:
<ul>
<xsl:apply-templates select="//name">
<xsl:sort select="normalize-space(.)"/>
</xsl:apply-templates>
</ul>
...
<xsl:template match="name">
<li><xsl:value-of select="normalize-space(.)"/></li>
</xsl:template>
And I've figured out a way to spit out a 4-column table of
them (reading down), although I bet folks on this list could
demonstrate a better method:
<table border="1">
<xsl:variable name="Q" select="ceiling( count( //name )
div 4 )"/>
<xsl:for-each select="//name[ position() <= $Q]">
<xsl:variable name="Q1" select="position() + (1 * $Q)"/>
<xsl:variable name="Q2" select="position() + (2 * $Q)"/>
<xsl:variable name="Q3" select="position() + (3 * $Q)"/>
<tr>
<td><xsl:value-of select="normalize-space(.)"/></td>
<td><xsl:value-of select="normalize-space( /*//name[
$Q1] )"/></td>
<td><xsl:value-of select="normalize-space( /*//name[
$Q2] )"/></td>
<td><xsl:value-of select="normalize-space( /*//name[
$Q3] )"/></td>
</tr>
</xsl:for-each>
</table>
But how do I do both at once, i.e. generate a 4-column table (read
down) of *sorted* names? E.g. something like either
Alex Gaston Lisa Richard
Bonnie Hermine Matthew Shary
Colin Igor Nicole Tomas
Danielle Julia Otto Virginie
Earl Karl Paula Walter
Fiona
or
Alex Gaston Matthew Tomas
Bonnie Hermine Nicole Virginie
Colin Igor Otto Walter
Danielle Julia Paula
Earl Karl Richard
Fiona Lisa Shary
As recently noted on this list, XPath 2 doesn't have a sort()
function. I'm betting if I knew where to look in the
reference guides on my shelf, this isn't too hard. But I'm
really not sure how to get started. Fancy grouping? Sequences? Sigh.
Note that for this particular application, thinking of the
things to be sorted as a set of strings is fine. But one can
imangine wanting to the same thing with nodes that are more
complex. In any case, Thanks in advance.
Appendix 1
-------- -
Enormously simplified input for testing. 2 points to she who
first posts what this list of names is.
<?xml version="1.0" encoding="UTF-8"?>
<names>
<name>Julia</name>
<name>Virginie</name>
<name>Bonnie</name>
<name>Paula</name>
<name>Lisa</name>
<name>Danielle</name>
<name>Fiona</name>
<name>Nicole</name>
<name>Alex</name>
<name>Shary</name>
<name>Earl</name>
<name>Gaston</name>
<name>Colin</name>
<name>Matthew</name>
<name>Hermine</name>
<name>Igor</name>
<name>Karl</name>
<name>Otto</name>
<name>Richard</name>
<name>Tomas</name>
<name>Walter</name>
</names>
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail:
<mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--
--~------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--~--