RE: counter

Subject: RE: counter
From: Kay Michael <Michael.Kay@xxxxxxx>
Date: Thu, 22 Jun 2000 19:08:35 +0100
> The way to print something every fifty <item> elements is:
> >
> > <xsl:template match="item[position() mod 50 = 1]">
> > <fifty-items>
> > Here's the next 50:
> > <xsl:for-each select=". | 
> following-sibling::item[position() &lt; 50]">
> >   <item><xsl:value-of select="."/></item>
> > </xsl:for-each>
> > </fifty-items>
> > </xsl:template>
>  
> a. I found that when running this I was getting the item 
> content repeated in the ouput for each element where the expression in the
template 
> match attribute was false. I put this down to a built-in template being
called 
> for those elements, is this correct ?

Yes. Sorry I didn't give all the detail of the solution, I like to leave
something to the reader :-)
> 
> b. I changed the code such that the position() test was applied to the
> apply-templates instruction...

> This did not display the extra output, presumably because the 
> template was able to handle all item elements passed to it.

Yes.
> However I did notice a significant performance improvement over Mike's
code which was 
> disproportionate to the number of item elements in the source document.
For example :
> 
> No. of                   Seconds to run  Seconds to run
> Item Elements        Original Code    Modified Code
> 100                                1                       1
> 200                                2                       1
> 400                                7                       2
> 800                               43                     5
> 
> Can someone explain the reason for these differences ?

Which processor?

I'm not surprised by the result. Putting the test in <xsl:apply-templates>
will do a single scan of the 800 elements, testing each one to see if its
position is a multiple of 50, and will then apply the template to each of
these nodes. Putting the test in the template match pattern means that you
will test the pattern against all 800 nodes, and for each one, its position
relative to its siblings has to be calculated. In Saxon, this can only be
done by counting the number of previous <item> siblings, so the overall
performance is O(n*n).

Of course it's possible in theory to optimise this, by having the
pattern-matching logic recognise that the position of an item relative to
its siblings is the same (in this case) as its position relative to the
node-set being processed. But Saxon isn't quite that clever yet.

Thanks for pointing this out. Using positional predicates in match patterns
is generally a bad idea.

Mike Kay


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list


Current Thread