My original requirement was to pass in parameters to the XSL file using C# and transform the XML on-the-fly. Therefore, I used xsl:param tags to hold the input values and generate a portion of XML based on this. I had a few problems matching templates and keys based on parameters, as this is not valid.
I therefore, generated by keys based on all the data and filtered the data I required based on the parameters.
The following code describes a full example using: Parameters, Keys and grouping. The aim is to dynamically group events by year and sort them in a descending order.
Grouping.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xml" href="stylesheet.xsl"?>
<theme>
<styles>
<style id="style1">
<title>Test Style 1</title>
<elements>
<element id="element1">
<title>Test Element 1</title>
<events>
<event id="event11" date="2008-10-13">
<title>Test Event 1</title>
</event>
<event id="event12" date="2009-03-18">
<title>Test Event 2</title>
</event>
<event id="event13" date="2009-02-26">
<title>Test Event 3</title>
</event>
<event id="event14" date="2011-04-12">
<title>Test Event 4</title>
</event>
<event id="event15" date="2010-01-01">
<title>Test Event 5</title>
</event>
<event id="event16" date="2010-07-06">
<title>Test Event 6</title>
</event>
</events>
</element>
<element id="element2">
<title>Test Element 2</title>
<events>
<event id="event21" date="2001-10-13">
<title>Test Event 1</title>
</event>
<event id="event22" date="2001-03-18">
<title>Test Event 2</title>
</event>
<event id="event23" date="2007-02-26">
<title>Test Event 3</title>
</event>
<event id="event24" date="2008-04-12">
<title>Test Event 4</title>
</event>
<event id="event25" date="2010-01-01">
<title>Test Event 5</title>
</event>
<event id="event26" date="2010-07-06">
<title>Test Event 6</title>
</event>
</events>
</element>
</elements>
</style>
<style id="style2">
<title>Test Style 2</title>
<elements>
<element id="element3">
<title>Test Element 3</title>
<events>
<event id="event31" date="2003-10-13">
<title>Test Event 1</title>
</event>
<event id="event32" date="2007-03-18">
<title>Test Event 2</title>
</event>
<event id="event33" date="2007-02-26">
<title>Test Event 3</title>
</event>
<event id="event34" date="2010-04-12">
<title>Test Event 4</title>
</event>
<event id="event35" date="2010-01-01">
<title>Test Event 5</title>
</event>
<event id="event36" date="2010-07-06">
<title>Test Event 6</title>
</event>
</events>
</element>
</elements>
</style>
</styles>
</theme>
Stylesheet.xsl
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt">
<!-- Parameters -->
<xsl:param name="style">style1</xsl:param>
<xsl:param name="element">element1</xsl:param>
<!-- Create a key based on the YYYY portion of the start_date attribute -->
<xsl:key
name="keyYear"
match="events/event"
use="substring(@date, 1, 4)"
/>
<xsl:key
name="keyEventID"
match="events/event"
use="@id"
/>
<!-- Match default template -->
<xsl:template match="/">
<xsl:apply-templates select="/theme/styles/style[@id=$style]/elements/element[@id=$element]/events" />
</xsl:template>
<!-- matches on events, so only outputs once [per stream] -->
<xsl:template match="events">
<table>
<xsl:for-each select="//event[generate-id()=generate-id(key('keyYear', substring(@date, 1, 4))[1])]">
<xsl:sort select="substring(@date, 1, 4)" order="descending" />
<!-- Save the Year to a variable -->
<xsl:variable name="varCurrentYear"><xsl:value-of select="substring(@date, 1, 4)" /></xsl:variable>
<!-- Select all the events belonging to the year -->
<xsl:variable name="lstEventPerYear" select="/theme/styles/style[@id=$style]/elements/element[@id=$element]/events/event[substring(@date, 1, 4)=$varCurrentYear]" />
<!-- Store child count -->
<xsl:variable name="varChildCount"><xsl:value-of select="count($lstEventPerYear[generate-id(.) = generate-id(key('keyEventID', @id)[1])])" /></xsl:variable>
<!-- Output year only if there are sub elements -->
<xsl:if test="$varChildCount > 0">
<tr>
<td>
<h3><xsl:value-of select="$varCurrentYear" /></h3>
</td>
</tr>
<xsl:for-each select="$lstEventPerYear[generate-id(.) = generate-id(key('keyEventID', @id)[1])]">
<xsl:sort select="title" />
<tr>
<td>
<h4>
<xsl:value-of select="title" />
<xsl:text disable-output-escaping="yes">&nbsp;</xsl:text>
[<xsl:value-of select="ms:format-date(@date, 'dd MMM yyyy')"/>]
</h4>
</td>
</tr>
</xsl:for-each>
</xsl:if>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
No comments:
Post a Comment