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

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


Subject: [xsl] Re: Re: Re: Unbounded element grouping/concatenation
From: "Dimitre Novatchev" <dnovatchev@xxxxxxxxx>
Date: Thu, 11 Dec 2003 21:17:11 +0100

>
> The recursive algorithm I wish I could use is exactly as you stated.
> Something like the following (not tested, might be typos)
>
>   <xsl:template match="records">
>     <xsl:apply-templates select="record[@type = 'normal']"/>
>   </xsl:template>
>
>   <xsl:template match="record[@type = 'normal']">
>     <record>
>       <xsl:copy-of select="*" />
>       <xsl:if test="following-sibling::record[1][@type='continuation']">
>         <xsl:apply-templates select=following-sibling::record[1]"/>
>       </xsl:if>
>     </record>
>   </xsl:template>
>
>   <xsl:template match="record[@type = 'continuation']">
>     <xsl:copy-of select="*" />
>     <xsl:if test="following-sibling::record[1][@type='continuation']">
>       <xsl:apply-templates select=following-sibling::record[1]"/>
>     </xsl:if>
>   </xsl:template>
>
> However, this gives me a stack overflow error in Xalan (which I'm
> stuck with for now). Actually, it gives me a stack overflow in Saxon
> too -- I probably need to use named templates or something to get the
> tail recursion optimization to work.
>

Raman,

The recursive algorithm works very well for me with XalanJ2.4.1. It is also
much faster than the variant with generate-id().

I tested it with a record (type="normal"), which has 200 following siblings
record (type="continuation").

With this source xml the recursive transformationtakes 781 ms to run. The
transformation with generate-id() takes 18687 ms.

Here's the (corrected) recursive algorithm:

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*" />

  <xsl:template match="@* | node()">
    <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[@type = 'normal']">
    <xsl:copy>
      <xsl:apply-templates select="@* | node()" />
      <xsl:apply-templates
       select="following-sibling::record[1][@type='continuation']"/>
    </xsl:copy>
  </xsl:template>

  <xsl:template match="record[@type = 'continuation']">
    <xsl:copy-of select="." />
    <xsl:apply-templates
     select="following-sibling::record[1][@type='continuation']"/>
  </xsl:template>
</xsl:stylesheet>


Here's the transformation that uses generate-id():

<xsl:stylesheet version="1.0"
 xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output omit-xml-declaration="yes" indent="yes"/>
  <xsl:strip-space elements="*"/>

  <xsl:template match="@* | node()">
    <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:copy>
      <xsl:apply-templates select="@* | node()" />
      <xsl:if test="following-sibling::record[1][@type = 'continuation']">
      <xsl:apply-templates
         select="following-sibling::record[@type = 'continuation' and
           generate-id(preceding-sibling::record[@type = 'normal'][1]) =
           generate-id(current())]"/>
      </xsl:if>
    </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

You should not have any problems with the recursive transformation. My
configuration is: Pentium 4, 1.7GHz, 256MB RAM, W2K.



=====
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
Keywords
xml