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: mark bordelon <markcbordelon@xxxxxxxxx>
Date: Thu, 9 Apr 2009 13:50:16 -0700 (PDT)
Mike,

Thanks for your idea. I would like to avoid two transformations, since,
ideally, the transformation should take place in the client's browser and I
have not been able to perform more than one transform with the code I have
been working with. However, I am interested in the solution as a learning
exrcise and will try it out in Altova Spy.

Mark

--- On Thu, 4/9/09, Michael Ludwig <milu71@xxxxxx> wrote:


From: Michael Ludwig <milu71@xxxxxx>
Subject: Re: [xsl] XSL performance question: running count of attributes using
axes and sum()
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Date: Thursday, April 9, 2009, 12:48 PM


-----Inline Attachment Follows-----


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"
  xmlns:exsl="http://exslt.org/common";
  extension-element-prefixes="exsl"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>

  <xsl:output indent="yes"/>

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

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

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

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

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

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

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

</xsl:stylesheet>

Current Thread