[XSL-LIST Mailing List Archive Home] [By Thread] [By Date]

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 14:14:19 -0700 (PDT)

Lieber Michael,

I moved onto your solution next, especially since corrected my notion that it
was a multiple transformation. I have added nothing to the transform, although
I will like to integrate the floor() function on the length attribute
somewhere in the process, to see if this can work in XSLT1.0

Anyway, this line is causing an error in Altova Spy:

<xsl:variable name="sums" select="exsl:node-set($sums-rtf)"/>
 
"File Untitled4.xsl: XSL transformation failed
Error in XPath expression: Unknown function - Name and number of arguments do
not match any function signature in the static context -
'http://exslt.org/common:node-set'

Kannst Du mir bitte verklaeren, was ich woll falsch gemacht hab' ;-)

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
Keywords