PANVEGA’s Blog

DotNet Development, SharePoint Customizing, Silverlight, MS Infrastructure and other tips and tricks

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 unique TeamID-->
<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 by Team, 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) &gt; 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:

http://www.jenitennison.com/xslt/grouping

http://www.w3.org/TR/xslt20/

http://www.stylusstudio.com/xsllist/200504/post00580.html

Leave a Reply

XHTML: You can use these tags: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <pre> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>