Re: [xsl] XSL performance question: running count of attributes using axes and sum()

Subject: Re: [xsl] XSL performance question: running count of attributes using axes and sum()
From: Michael Ludwig <milu71@xxxxxx>
Date: Thu, 9 Apr 2009 21:48:58 +0200
mark bordelon schrieb am 09.04.2009 um 11:22:04 (-0700):

> In transforming the <syl> tags below into HTML table cells to display
> them, I need to format each cell with a green color with the running
> total of the @length attributes is a multiple of four. Ideally having
> the ability to do running totals in another variable would be great,
> but not the best XSL-esque solution, so I am using axes instead.

What's wrong with variables? You could combine a variable to look up the
result with an approach using the sibling axis, an intermediate result,
and the node-set() extension function. The following example should give
you an idea of how to do such a multi-pass approach in XSLT 1.0. It
should perform quite reasonably.

To speed it up even more, split this into two transformations where the
intermediate result is written to a document which is then used as a
lookup table together with a key in the second transformation.

(I wonder whether it is possible, in 1.0, to have an key work on a
variable that I build while processing? I guess the answer is no.)

Michael Ludwig

<?xml version="1.0" encoding="ISO-8859-1"?>
<xsl:stylesheet version="1.0"

  <xsl:output indent="yes"/>

  <xsl:template match="poem">
      <!-- Check correctness of sum operation: -->
      <SUM><xsl:value-of select="sum( //@length )"/></SUM>

  <xsl:variable name="len-rtf"><!-- Result Tree Fragment -->
    <xsl:apply-templates select="//syl[@length]" mode="len"/>

  <!-- Build a table to hold @length values for all syl elements. -->
  <xsl:template match="syl" mode="len">
    <LEN id="{ generate-id() }" len="{ @length }"/>

  <!-- Build another table to cache sums -->
  <xsl:variable name="sums-rtf"><!-- RTF -->
    <xsl:apply-templates select="exsl:node-set($len-rtf)/*[1]"/>

  <xsl:template match="LEN">
    <xsl:param name="sum" select="0"/>
      <xsl:copy-of select="@*"/>
      <xsl:attribute name="sum">
        <xsl:value-of select="$sum + @len"/>
    <xsl:apply-templates select="following-sibling::*[1]">
      <xsl:with-param name="sum" select="$sum + @len"/>

  <!-- Promote the RTF to a node-set so we can use the axes. -->
  <xsl:variable name="sums" select="exsl:node-set($sums-rtf)"/>

  <xsl:template match="syl">
      <xsl:attribute name="running">
        <xsl:value-of select="
          $sums/LEN[@id = generate-id(current())]/@sum"/>
      <xsl:apply-templates select="@*|node()"/>

  <xsl:template match="@*|node()"><!-- copy template -->
    <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>


Current Thread