XSLT - Grouping same items

Tag: xslt Author: minnizhm Date: 2009-09-08

I have the following XML:

  <Info>
    <Name>Dan</Name>
    <Age>24</Age>
  </Info>
  <Info>
    <Name>Tom</Name>
    <Age>15</Age>
  </Info>
  <Info>
    <Name>Dan</Name>
    <Age>24</Age>
  </Info>
  <Info>
    <Name>James</Name>
    <Age>18</Age>
  </Info>

And I need to produce the following HTML:

<ul class="data">
<li>Dan</li>
<li>Dan</li>
</ul>

<ul class="data">
<li>James</li>
</ul>

<ul class="data">
<li>Tom</li>
<li>Tom</li>
</ul>

As well as producing the output it needs to sort based on the Name also. Any help appreciated, started by looking at group-by but couldnt work out how to get it finished:

Pretty sure its wrong?

<xsl:for-each-group select="Info" group-by="@Name">??????
<xsl:for-each-group select="current-group()" sort-by="@Name">

Best Answer

I don't have an XSLT 2.0 parser, but to do it in XSLT 1.0 at least you could use Muenchian Grouping to do this...

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:output encoding="utf-8" method="html" version="1.0"/>

    <xsl:key name="Names" match="Name" use="."/>

    <xsl:template match="/">
    	<xsl:for-each select="//Info[generate-id(Name) = generate-id(key('Names', Name)[1])]">
    	<xsl:sort select="Name" />
    	<ul class="data">
    		<xsl:for-each select="key('Names', Name)">
    		<li><xsl:value-of select="." /></li>
    		</xsl:for-each>
    		</ul>
    	</xsl:for-each>
    </xsl:template>
</xsl:stylesheet>

Other Answer1

I'm not sure why your result has two 'Tom' elements, I assume you have an extra node in the XML that you didn't provide in your sample.

Anyway, the XSLT would look something like this:

<xsl:for-each-group select="Info" group-by="Name">
    <xsl:sort select="current-grouping-key()"/>
    <ul class="data">
    <xsl:for-each select="current-group()/Name">
        <li><xsl:value-of select="." /></li>
    </xsl:for-each>
    </ul>
</xsl:for-each-group>

I don't have an XSLT 2.0 parser handy to test it, but I think that should work.

Other Answer2

I don't have an xslt 2.0 parser to test this, but at the very least you will need to change "@Name" to just "Name", since it is a subelement not an attribute.

comments:

Im no closer to a solution, Im doing something wrong!