xsl-list
[Top] [All Lists]

Re: XSLT grouping without Muenchen Method

2004-08-30 22:54:49
On Mon, 30 Aug 2004 20:47:46 +0200
 "cking" <cking(_at_)telenet(_dot_)be> wrote:

Hello Anton,

thanks for the provided solution. Unfortunately I can not use a two step solution, as I can only integrate one stylesheet into the application. XT has a node-set function and this can indeed used as a solution for my problem. Normally I try to avoid to use extension functions as I want to have my stylesheets processor independent, but in this case I do not see any other solution to solve it.
Anyway thanks.

Kind regards,
Ismaël

Hi Ismael,

Here's a solution in two passes:

--- pass1.xsl ---
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/root">
 <root>
  <xsl:apply-templates select="object"/>
 </root>
</xsl:template>
<xsl:template match="object">
 <object name="{(_at_)name}" instance="{concat('Instance', instance/@number)}">
  <xsl:attribute name="interval">
<xsl:value-of select="substring-before(instance/sample/@date_time, ':')"/>
   <xsl:call-template name="calculate-interval">
<xsl:with-param name="time" select="substring-after(instance/sample/@date_time, ':')"/>
   </xsl:call-template>
  </xsl:attribute>
 </object>
</xsl:template>
<xsl:template name="calculate-interval">
 <xsl:param name="time"/>
 <xsl:variable name="hour" select="number(substring-before($time, ':'))"/>
 <xsl:choose>
  <xsl:when test="$hour &lt; 15">:00:00</xsl:when>
  <xsl:when test="$hour &lt; 30">:15:00</xsl:when>
  <xsl:when test="$hour &lt; 45">:30:00</xsl:when>
  <xsl:otherwise>:45:00</xsl:otherwise>
 </xsl:choose>
</xsl:template>
</xsl:stylesheet>

This will produce this intermediate xml file:
<root>
<object name="object1" instance="Instance0" interval="2004-08-30 15:00:00"/> <object name="object2" instance="Instance0" interval="2004-08-30 15:30:00"/> <object name="object3" instance="Instance0" interval="2004-08-30 15:00:00"/> <object name="object4" instance="Instance1" interval="2004-08-30 15:00:00"/> <object name="object5" instance="Instance1" interval="2004-08-30 15:30:00"/> <object name="object6" instance="Instance1" interval="2004-08-30 15:00:00"/>
</root>

Which then you can transform in a second pass:

--- pass2.xsl ---
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
<xsl:output method="text"/>
<xsl:template match="/root">
 <xsl:apply-templates select="object">
  <xsl:sort select="@interval"/>
  <xsl:sort select="@instance"/>
 </xsl:apply-templates>
</xsl:template>
<xsl:template match="object">
 <xsl:variable name="interval" select="@interval"/>
 <xsl:variable name="instance" select="@instance"/>
<xsl:if test="not(preceding-sibling::object[(_at_)interval=$interval and @instance=$instance])">
  <!-- first of group -->
<xsl:apply-templates select="self::object | following-sibling::object[(_at_)interval=$interval and @instance=$instance]"
mode="write"/>
  <xsl:value-of select="@instance"/>
  <xsl:text>;</xsl:text>
  <xsl:value-of select="@interval"/>
  <xsl:text>&#xA;</xsl:text>
 </xsl:if>
</xsl:template>
<xsl:template match="object" mode="write">
 <xsl:value-of select="@name"/>
 <xsl:text>;</xsl:text>
</xsl:template>
</xsl:stylesheet>

Which will give you this text file:
object1;object3;Instance0;2004-08-30 15:00:00
object4;object6;Instance1;2004-08-30 15:00:00
object2;Instance0;2004-08-30 15:30:00
object5;Instance1;2004-08-30 15:30:00

I'm not familiar with XT, does it support node-sets?
If so, you could use that to do it in one pass only.

HTH,

Best regards
Anton Triest