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: Dimitre Novatchev <dnovatchev@xxxxxxxxx>
Date: Sat, 11 Apr 2009 21:54:51 -0700
Quite straight-forward solution using FXSL:

This transformation:

<xsl:stylesheet version="2.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 xmlns:f="http://fxsl.sf.net/";
 xmlns:xs="http://www.w3.org/2001/XMLSchema";
 exclude-result-prefixes="xs f"
>

  <xsl:import href="../f/func-scanlDVC.xsl"/>
  <xsl:import href="../f/func-Operators.xsl"/>

  <!-- To be applied on testFunc-scanlDVC4.xml -->
  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:template match="/*/line">
	  <xsl:variable name="vRunningTotals" as="xs:double*"
	    select="f:scanl(f:add(),
	                          0,
	                          for $syl in /*/line/word/syl
	                             return
	                               if($syl/@elide eq 'true')
	                                 then 0
	                                 else floor($syl/@length)
	                    )
	           "/>

   <xsl:for-each select="word/syl/@length">
     <xsl:variable name="vPos" as="xs:integer"
       select="position()"/>
     <xsl:sequence select=
      "'SYL ', ../text(),

      ' SUM:', $vRunningTotals[$vPos],

      'COLOR:',
       if($vRunningTotals
               [$vPos] mod 4 eq 0)
         then 'GREEN'
         else (),
         '&#xA;'
      "/>
   </xsl:for-each>
 </xsl:template>
</xsl:stylesheet>

when applied on this XML document:

<poem>
	<line id="1">
		<word id="1">
			<syl length="2">Ar</syl>
			<syl length="1">ma</syl>
		</word>
		<word id="2">
			<syl length="1">vi</syl>
			<syl length="2">rum</syl>
		</word>
		<word id="3">
		  <syl length="1">que</syl>
		</word>
		<word id="4">
			<syl length="1">ca</syl>
			<syl length="2">no</syl>
		</word> ,
		<word id="5">
			<syl length="2">Tro</syl>
			<syl length="2">iae</syl>
		</word>
		<word id="6">
			<syl length="2">qui</syl>
		</word>
		<word id="7">
			<syl length="2">pri</syl>
			<syl length="1">mus</syl>
		</word>
		<word id="8">
			<syl length="1">ab</syl>
		</word>
		<word id="9">
			<syl length="2">o</syl>
			<syl length="2">ris</syl>
		</word>
	</line>
	<line id="2">
		<word>
			<syl length="2">li</syl>
			<syl length="1.5">to</syl>
			<syl length="1">ra</syl>
		</word> ,
		<word id="15">
			<syl length="2">mul</syl>
			<syl elide="true" length="1">tum</syl>
		</word>
		<word id="16">
			<syl length="2">il</syl>
			<syl elide="true" length="1">le</syl>
		</word>
		<word id="17">
			<syl length="2">et</syl>
		</word>
		<word id="18">
			<syl length="2">ter</syl>
			<syl length="2">ris</syl>
		</word>
		<word id="19">
			<syl length="2">iac</syl>
			<syl length="2">ta</syl>
			<syl length="1">tus</syl>
		</word>
		<word id="20">
			<syl length="1">et</syl>
		</word>
		<word id="21">
			<syl length="2">al</syl>
			<syl length="2">to</syl>
		</word>
	</line>
</poem>

produces the wanted result:


 SYL Ar SUM: 0 COLOR: GREEN
 SYL ma SUM: 2 COLOR:
 SYL vi SUM: 3 COLOR:
 SYL rum SUM: 4 COLOR: GREEN
 SYL que SUM: 6 COLOR:
 SYL ca SUM: 7 COLOR:
 SYL no SUM: 8 COLOR: GREEN
 SYL Tro SUM: 10 COLOR:
 SYL iae SUM: 12 COLOR: GREEN
 SYL qui SUM: 14 COLOR:
 SYL pri SUM: 16 COLOR: GREEN
 SYL mus SUM: 18 COLOR:
 SYL ab SUM: 19 COLOR:
 SYL o SUM: 20 COLOR: GREEN
 SYL ris SUM: 22 COLOR:

 SYL li SUM: 0 COLOR: GREEN
 SYL to SUM: 2 COLOR:
 SYL ra SUM: 3 COLOR:
 SYL mul SUM: 4 COLOR: GREEN
 SYL tum SUM: 6 COLOR:
 SYL il SUM: 7 COLOR:
 SYL le SUM: 8 COLOR: GREEN
 SYL et SUM: 10 COLOR:
 SYL ter SUM: 12 COLOR: GREEN
 SYL ris SUM: 14 COLOR:
 SYL iac SUM: 16 COLOR: GREEN
 SYL ta SUM: 18 COLOR:
 SYL tus SUM: 19 COLOR:
 SYL et SUM: 20 COLOR: GREEN
 SYL al SUM: 22 COLOR:
 SYL to SUM: 24 COLOR: GREEN





--
Cheers,
Dimitre Novatchev
---------------------------------------
Truly great madness cannot be achieved without significant intelligence.
---------------------------------------
To invent, you need a good imagination and a pile of junk
-------------------------------------
Never fight an inanimate object
-------------------------------------
You've achieved success in your field when you don't know whether what
you're doing is work or play



On Thu, Apr 9, 2009 at 11:22 AM, mark bordelon <markcbordelon@xxxxxxxxx>
wrote:
>
> Dear Gents,
>
> Getting quite comfortable using XSL. Since I am using alot more heavy-duty
XSL, I am now hitting barriers with performance. My quesiton to the forum is
for once, not a beginner's question!
>
> 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. I have tried solutions with count and
sum, but performance is slow: 756 lines like the ones below mean thousands of
syllables to check, each with its own axis computation -- the complete xform
takes more than an hour!
>
> Can anyone point me to a solution that is more performant yet still
elegant/simple?
>
> An aside: it seems that ceiling() is an Xpath1.0 function, but oddly enough
not floor() -- Altova SPY complains about floor until I change the stylesheet
to version 2.0 (sigh). I would love this to transform in XSL1.0 if possible,
and rounding down each length to the integer is essential to acheive the
correct formatting result.
>
> Thanks in advance for any help on this.
>
> XML:
>
> <poem>
> B  B  B  B <line id="1">
> B  B  B  B  B  B  B  B <word id="1">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">Ar</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="1">ma</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="2">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="1">vi</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">rum</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <syl length="1">que</syl>
> B  B  B  B  B  B  B  B <word id="3">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="1">ca</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">no</syl>
> B  B  B  B  B  B  B  B </word> ,
> B  B  B  B  B  B  B  B <word id="4">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">Tro</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">iae</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="5">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">qui</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="6">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">pri</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="1">mus</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="7">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="1">ab</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="8">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">o</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">ris</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B </line>
> B  B  B  B <line id="2">
> B  B  B  B  B  B  B  B <word>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">li</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="1.5">to</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="1">ra</syl>
> B  B  B  B  B  B  B  B </word> ,
> B  B  B  B  B  B  B  B <word id="15">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">mul</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl elide="true" length="1">tum</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="16">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">il</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl elide="true" length="1">le</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="17">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">et</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="18">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">ter</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">ris</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="19">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">iac</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">ta</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="1">tus</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="20">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="1">et</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B  B  B  B  B <word id="21">
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">al</syl>
> B  B  B  B  B  B  B  B  B  B  B  B <syl length="2">to</syl>
> B  B  B  B  B  B  B  B </word>
> B  B  B  B </line>
> </poem>
>
>
> XSL template:
>
> <xsl:template match="syl">
>
> <xsl:variable name="line_id"><xsl:value-of
select="node()/ancestor::line/@id" /></xsl:variable>
>
> <xsl:variable name="current_quantity"><xsl:value-of
select="sum(preceding::syl[ancestor::line/@id = $line_id and (not(@elide) or
@elide='false') ]/floor(@length))" /></xsl:variable>
>
> <xsl:variable name="color"><xsl:choose><xsl:when test="@length=2 and
($current_quantity mod 4 =
0)">background-color:#EEFFEE;</xsl:when></xsl:choose></xsl:variable>
>
> <td style="{$color}"><xsl:value-of select="text()" /></td>
>
> </xsl:template>

Current Thread