Easy Grouping in XSLT 1.0
Posted by PANVEGA on June 10, 2009
I was asked to implement a grouping by TEAM with all the employees regarding to the Team Name into a SharePoint People Results Webpart. Here I am gonna show you a very nice aproach how to realize this custom request.
I read in so many posts how to create a proper grouping results in XSLT 1.0. XSLT 2.0 makes grouping even easier than Steve did. The XSLT 2.0 xsl:for-each-group instruction iterates across a series of groups, with the criteria for grouping specified by its attributes. While XSLT 1.0 lets you sort elements, it still forces you to jump through several hoops to do anything extra with the groups that result from the sort.
Here is a snipped of the XML file:
<?xml version="1.0" ?> <All_Results> <Result> <Team>BI</Team> <PreferedName>Alex</PreferedName> <Function>1</Function> </Result>
<Result> <Team>BI</Team> <PreferedName>Max</PreferedName> <Function>3</Function> </Result>
<Result> <Team>BDEV</Team> <PreferedName>Moritz</PreferedName> <Function>1</Function> </Result>
</All_Results>
XSLT 2.0 example:
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="2.0">
<xsl:output method="text"/>
<xsl:template match="Result">
<xsl:for-each-group select="file" group-by="@team">
<xsl:value-of select="current-grouping-key()"/>
<xsl:text>
</xsl:text>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
XSLT 1.0 Example
First, you must define the keys required to group the <Result> elements. You will need one for the team, and one for the preferredname
<xsl:key name="groupby" match="Result" use="team"/> <xsl:key name="employeeName" match="Result" use="preferredname" /> <xsl:template match="All_Results"> <!--Select the first element of each group of elements for each uniqueTeamID--> <xsl:for-each select="Result[generate-id(.) =generate-id(key('groupby', team)[1])]" > <xsl:sort select="team" order="ascending" /> <xsl:variable name="TeamID"><xsl:value-of select="team" /></xsl:variable> <!-- Select all the Employees belonging to the Team --> <xsl:variable name="lstEmployee" select="//Result[team=$TeamID]" /> <tr > <td colspan="4" >Team: <xsl:value-of select="$lstEmployee[1]/team" /></td></tr> <!--The<Result>elements in this list must now be grouped by preferedname. This is similar to grouping byTeam, except that in this case you only need to select elements in the list contained in the variable; you do not need to select elements from the entire result set.--> <tr style="height:6px;"><td colspan="4"></td></tr> <xsl:for-each select="$lstEmployee[generate-id(.) = generate-id(key('employeeName', preferredname)[1])]"> <xsl:sort select="preferredname" order="ascending" /> <xsl:variable name="lngEmployeeID" select="preferredname" /> <a href="{$url}" id="{concat('CSR_',$id)}" target="_blank"> <xsl:value-of select="$lstEmployee[preferredname=$lngEmployeeID]/preferredname" /> <xsl:if test='string-length(jobtitle) > 0'> <xsl:value-of select="concat(', ',jobtitle)" /> </xsl:if> </a> </xsl:for-each>
</xsl:template>
Of course, you can call a template instead of the for-each.
<!-- Show details for Employees in Team --> <xsl:call-template name="EmployeesInTeam"> <xsl:with-param name="lstEmployee" select="$lstEmployee" /> </xsl:call-template>
More Informations: