I am hoping that someone can help me asI have been trying to figure out how to make a transformation of a data set into a table structure that is grouped on multiple levels. The first level is the Event Date, the second is the Company Name, and the last is the by the Users.
The following is the XML.
<xmlData>
<records>
<record>
<userid>1</userid>
<usersname>Jane Doe</usersname>
<companyname>Company A</companyname>
<eventdate>01 FEB 2017</eventdate>
<jeventdate>2457786</jeventdate>
</record>
<record>
<userid>3</userid>
<usersname>Jane Doe</usersname>
<companyname>Company B</companyname>
<eventdate>01 FEB 2017</eventdate>
<jeventdate>2457786</jeventdate>
</record>
<record>
<userid>2</userid>
<usersname>Joe Smith</usersname>
<companyname>Company B</companyname>
<eventdate>01 DEC 2016</eventdate>
<jeventdate>2457724</jeventdate>
</record>
<record>
<userid>2</userid>
<usersname>Joe Smith</usersname>
<companyname>Company B</companyname>
<eventdate>01 JAN 2017</eventdate>
<jeventdate>2457755</jeventdate>
</record>
<record>
<userid>2</userid>
<usersname>Joe Smith</usersname>
<companyname>Company B</companyname>
<eventdate>01 FEB 2017</eventdate>
<jeventdate>2457786</jeventdate>
</record>
</records>
</xmlData>
The results that I am trying to get to is shown in the following simple HTML output.
<h1>01 DEC 2016</h1>
<h2>Company B</h2>
<table>
<tr><td>2</td><td>Joe Smith</td></tr>
</table>
<h1>01 JAN 2017</h1>
<h2>Company B</h2>
<table>
<tr><td>2</td><td>Joe Smith</td></tr>
</table>
<h1>01 FEB 2017</h1>
<h2>Company A</h2>
<table>
<tr><td>1</td><td>Jane Doe</td></tr>
</table>
<h2>Company B</h2>
<table>
<tr><td>3</td><td>Dave Dodd</td></tr>
<tr><td>2</td><td>Joe Smith</td></tr>
</table>
The issue I am having is actually two parts. The first is getting the three levels of depth. The second is getting all the records and not just the first few.
Here is the XSL that I have been working with.
<xsl:key name="monthof" match="record" use="eventdate"/>
<xsl:key name="companyof" match="record" use="concat(eventdate,'|',companyname)"/>
<xsl:key name="userof" match="record" use="concat(eventdate,'|',companyname,'|',usersname)"/>
<xsl:template match="xmlData/records">
<xsl:for-each select="record[key('monthof',eventdate)]">
<xsl:sort select="jeventdate"/>
<xsl:variable name="lstEventDate" select="key('monthof',eventdate)" />
<h2><xsl:value-of select="eventdate"/></h2>
<xsl:for-each select="key('companyof',concat(eventdate,'|',companyname))">
<xsl:sort select="companyname"/>
<h3>
<xsl:value-of select="companyname"/>
</h3>
<table>
<xsl:for-each select="key('userof',concat(eventdate,'|',companyname,'|',usersname))">
<tr>
<td><xsl:value-of select="userid"/></td>
<td><xsl:value-of select="usersname"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
And here is the output that I am getting.
01 DEC 2016
Company B
2 Jane Doe
01 JAN 2017
Company B
2 Jane Doe
01 FEB 2017
Company A
1 Joe Smith
01 FEB 2017
Company B
1 Joe Smith
Company B
3 Dave Dodd
01 FEB 2017
Company B
1 Joe Smith
Company B
2 Jane Doe
The keys you have defined are fine but you need then to use them, as already pointed in a comment, with the Muenchian grouping approach:
<xsl:template match="xmlData/records">
<xsl:for-each select="record[generate-id() = generate-id(key('monthof',eventdate)[1])]">
<xsl:sort select="jeventdate"/>
<h2><xsl:value-of select="eventdate"/></h2>
<xsl:for-each select="key('monthof', eventdate)[generate-id() = generate-id(key('companyof',concat(eventdate,'|',companyname))[1])]">
<xsl:sort select="companyname"/>
<h3>
<xsl:value-of select="companyname"/>
</h3>
<table>
<xsl:for-each select="key('companyof',concat(eventdate,'|',companyname))[generate-id() = generate-id(key('userof',concat(eventdate,'|',companyname,'|',usersname))[1])]">
<tr>
<td><xsl:value-of select="userid"/></td>
<td><xsl:value-of select="usersname"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:for-each>
</xsl:for-each>
</xsl:template>
You might want to check whether you can't move to XSLT 2.0 where it becomes a lot easier doing
<xsl:template match="xmlData/records">
<xsl:for-each-group select="record" group-by="eventdate">
<xsl:sort select="jeventdate"/>
<h2><xsl:value-of select="eventdate"/></h2>
<xsl:for-each-group select="current-group()" group-by="companyname">
<xsl:sort select="companyname"/>
<h3>
<xsl:value-of select="companyname"/>
</h3>
<table>
<xsl:for-each-group select="current-group()" group-by="usersname">
<tr>
<td><xsl:value-of select="userid"/></td>
<td><xsl:value-of select="usersname"/></td>
</tr>
</xsl:for-each-group>
</table>
</xsl:for-each-group>
</xsl:for-each-group>
</xsl:template>