xsl-list
[Top] [All Lists]

RE: [xsl] both sorting and grouping set of nodes

2009-12-03 04:28:50
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() &lt;= $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>
--~--

<Prev in Thread] Current Thread [Next in Thread>