Group and sort into muliple columns XSLT
I have a list of animals in XML. I want to group them by class and show them in tables with rows of three. I can accomplish this using XSLT 2.0 and for-each-group
<zoo>
<animal class="fish">Koi</animal>
<animal class="fish">Lamprey</animal>
<animal class="bird">Chicken</animal>
<animal class="fish">Firefish</animal>
<animal class="fish">Bluegill</animal>
<animal class="bird">Eagle</animal>
<animal class="fish">Eel</animal>
<animal class="bird">Osprey</animal>
<animal class="bird">Turkey</animal>
<animal class="fish">Guppy</animal>
</zoo>
The XSLT is:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" indent="yes" name="html" doctype-system="about:legacy-compat" />
<xsl:template match="/">
<html><head></head><body>
<xsl:for-each-group select="//animal" group-by="@class">
<table>
<xsl:for-each-group select="current-group()" group-adjacent="ceiling(position() div 3)">
<tr>
<xsl:for-each select="current-group()">
<xsl:apply-templates select="."/>
</xsl:for-each>
</tr&开发者_C百科gt;
</xsl:for-each-group>
</table>
</xsl:for-each-group>
</body></html>
</xsl:template>
<xsl:template match="animal">
<td><xsl:value-of select="."/></td>
</xsl:template>
</xsl:stylesheet>
The output is nearly perfect except that I need to sort the animal names.
I tried using <xsl:perform-sort select="current-group()"> Like Michael Kay suggested to someone here. But this resulted in a stack overflow. Any ideas how I can sort the names of the animals in my grouped and multi-columned list?
Add sort tag, inside the <xsl:for-each>
<xsl:for-each select="current-group()">
<xsl:sort data-type="text" select="." order="ascending"/>
<xsl:apply-templates select="."/>
</xsl:for-each>
Here's a solution that works (although I am not sure I understand why).
<xsl:variable name="unsorted" select="current-group()"/>
<xsl:variable name="sorted">
<xsl:perform-sort select="current-group()">
<xsl:sort select="."/>
</xsl:perform-sort>
</xsl:variable>
<xsl:for-each-group select="$sorted/animal" group-adjacent="ceiling(position() div 3)">
<tr>
<xsl:for-each select="current-group()">
<xsl:apply-templates select="."/>
</xsl:for-each>
</tr>
</xsl:for-each-group>
(Of course you don't need the "unsorted" variable for anything. It is just there for comparison)
The odd thing is that if I use $unsorted in the the for-each-group, It builds the unsorted list like I'd expect. However if I use $sorted I have to use "$sorted/animal" for reasons I don't quite understand.
精彩评论