[xsl] Re: Re: Re: Re: Unbounded element grouping/concatenation

Subject: [xsl] Re: Re: Re: Re: Unbounded element grouping/concatenation
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Fri, 12 Dec 2003 22:32:05 +0100
> > I could try still speeding up the non-recursive algorithm, by
> > using a faster search than linear to find the position of a
> > record node in the string with positions -- this will require
> > that all positions must have the same (some maximum) length.
> > Or I could record the positions in a node-set, for which
> > binary search is straight-forward.
> >
> > In case you are still not satisfied with the speed of the
> > non-recursive algorithm, just let me know :o)
>
> Well, I'm more than satisfied with it, but if you want to make
> it even faster, don't let me stop you :-)


> Dimitre,
>
> One change to your algorithm... the xsl:choose inside the record
> match is not required because the continuation records are copied
> when each header record is selected. Slightly simpler and I don't
> think I broke anything (gives me the same result for my test
> case anyway). Here is the new version:

Yes, I know...

Below is the next version, which is speeded up 10-30%. The change is that if
you knoe in advance that the maximum of possible immediate continuation
siblings is a number with N digits, then all position numbers in the string
of positions are coded with this fixed length. This allows not to use
delimiters between every two positions and not to search for a substring.
Instead, the position is found using direct addressing.

Here is the stylesheet (and yes, there's no xsl:choose now):

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform";
 >

  <xsl:output omit-xml-declaration="yes" indent="yes"/>

  <xsl:param name="pFormatPos" select="string('0001')"/>
  <xsl:variable name="vNumLength"
          select="string-length($pFormatPos)"/>

  <xsl:variable name="vTwiceNumLength"
                select="2 * $vNumLength"/>

  <xsl:variable name="vposArray">
    <xsl:for-each select="/*/record">
      <xsl:if test="@type = 'normal'">
        <xsl:number value="position()" format="{$pFormatPos}"/>
      </xsl:if>
    </xsl:for-each>
  </xsl:variable>



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

  <xsl:template match="records">
    <records>
      <xsl:apply-templates select="record[@type='normal']"/>
    </records>
  </xsl:template>

  <xsl:template match="record">
      <xsl:if test="@type='normal'">
        <xsl:variable name="vThisAndNext"
         select="substring($vposArray,
                           (position() - 1)*$vNumLength + 1,
                           $vTwiceNumLength
                           )"/>


         <xsl:variable name="vNumNested"
           select="substring($vThisAndNext, $vNumLength + 1)
                  -
                   substring($vThisAndNext, 1, $vNumLength)
                  - 1"/>
         <xsl:copy>
           <xsl:copy-of select="@* | node()"/>
           <xsl:if test="$vNumNested > 0">
             <xsl:copy-of select=
               "following-sibling::record
                           [position() &lt;= $vNumNested]"/>
           </xsl:if>
         </xsl:copy>
      </xsl:if>
  </xsl:template>

</xsl:stylesheet>


=====
Cheers,

Dimitre Novatchev.
http://fxsl.sourceforge.net/ -- the home of FXSL




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


Current Thread