I want to output grouped results in 3 columns. I'm not using a table so I guess I mean 3 sections of results (see the HTML) side-by-side.
I've grouped results according to the value of one of their nodes, and grouped under a heading which is the value of the node. For example:
<All_Results>
<Result>
<Dept>Finance</Dept>
<Name>Bob</Name>
</Result>
<Result>
<Dept>Finance</Dept>
<Name>Susan</Name>
</Result>
<Result>
<Dept>Sales</Dept>
<Name>Igor</Name>
</Result>
</All_Results>
is formatted like:
<li>
<h4>Finance</h4>
<ul>
<li>Bob</li>
</ul>
<ul>
<li>Susan</li>
</ul>
<h4>Sales</h4>
<ul>
<li>Igor</li>
</ul>
</li>
And this works and I'm happy with it. Now what I'm trying to do is create 3 columns side-by-side of Depts and their results (i.e., Names in this example). I'm expecting 9 possible Depts, but this may change in the future.
Here is my XSLT so far (all it does so far is the above formatting, no work on the columns yet, I'm not sure how to approach this problem):
<xsl:output method="html" />
<xsl:key name="results-by-dept" match="Result" use="Dept" />
<xsl:template match="All_Results">
<xsl:variable name="Rows" select="Result" />
<xsl:variable name="RowCount" select="count($Rows)" />
<ul class="deptList">
<xsl:for-each select="Result[count(. | key('results-by-dept', Dept)[1]) = 1]">
<xsl:sort select="Dept" order ="ascending"/>
<li>
<h4>
<xsl:value-of select="Dept" />
</h4>
<ul>
<xsl:for-each select="key('results-by-dept', Dept)">
<xsl:sort select="Name" />
<li>
<xsl:value-of select="Name"/>
</li>
</xsl:for-each>
</ul>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>
Any help would be much appreciated!
After discussion with the OP, I think this Use Case illustrates what he wants. The following sample input document shows 5 departments, with with one or two employees. The ordering of nodes is not significant.
<All_Results>
<Result>
<Dept>Finance</Dept>
<Name>Bob</Name>
</Result>
<Result>
<Dept>Engineering</Dept>
<Name>Inna</Name>
</Result>
<Result>
<Dept>Finance</Dept>
<Name>Susan</Name>
</Result>
<Result>
<Dept>Sales</Dept>
<Name>Igor</Name>
</Result>
<Result>
<Dept>Human resources</Dept>
<Name>Jane</Name>
</Result>
<Result>
<Dept>Admin</Dept>
<Name>Joe</Name>
</Result>
<Result>
<Dept>Engineering</Dept>
<Name>Dima</Name>
</Result>
<Result>
<Dept>Human resources</Dept>
<Name>Beth</Name>
</Result>
</All_Results>
The output is to be transformed like so (following listing). A HTML table is to be constructed with 3 columns but only one row. Each cell is to contain a HTML unordered lists of departmental employees, headed by the department name. Each column is to contain roughly one third of the departments, with the last column being ragged in this respect. Reading top-down and then left-to-right, departments should be sorted alphabetically. Within each department, employees should be listed alphabetically.
<table>
<tr>
<td>
<ul class="deptList">
<li>
<h4>Admin</h4>
<ul>
<li>Joe</li>
</ul>
</li>
<li>
<h4>Engineering</h4>
<ul>
<li>Dima</li>
<li>Inna</li>
</ul>
</li>
</ul>
</td>
<td>
<ul class="deptList">
<li>
<h4>Finance</h4>
<ul>
<li>Bob</li>
<li>Susan</li>
</ul>
</li>
<li>
<h4>Human resources</h4>
<ul>
<li>Beth</li>
<li>Jane</li>
</ul>
</li>
</ul>
</td>
<td>
<ul class="deptList">
<li>
<h4>Sales</h4>
<ul>
<li>Igor</li>
</ul>
</li>
</ul>
</td>
</tr>
</table>
This XSLT 1.0 style-sheet will give you 3 columns ...
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kDepartments" match="Result" use="Dept" />
<xsl:template match="/">
<table>
<tr>
<xsl:variable name="dept-count" select="count( */Result[
generate-id(.) = generate-id( key('kDepartments',Dept)[1])])" />
<xsl:for-each select="(//*)[position() <= 3]">
<xsl:variable name="column" select="position()" />
<td>
<ul class="deptList">
<xsl:for-each select="/*/Result[
generate-id(.) = generate-id( key('kDepartments',Dept)[1])]" >
<xsl:sort select="Dept" />
<xsl:variable name="DeptIndex" select="position()" />
<xsl:apply-templates select="self::Result[
(floor((($DeptIndex - 1)*3 div $dept-count)) + 1) = $column]" />
</xsl:for-each>
</ul>
</td>
</xsl:for-each>
</tr>
</table>
</xsl:template>
<xsl:template match="Result">
<h4>
<xsl:value-of select="Dept" />
</h4>
<ul>
<xsl:for-each select="key('kDepartments', Dept)">
<xsl:sort select="Name" />
<li>
<xsl:value-of select="Name"/>
</li>
</xsl:for-each>
</ul>
</xsl:template>
</xsl:stylesheet>