[XSL-LIST Mailing List Archive Home] [By Thread] [By Date] [Recent Entries] [Reply To This Message]

RE: XSLT 1.0 Stack Overflow Question

Subject: RE: XSLT 1.0 Stack Overflow Question
From: "Michael Kay" <mike@xxxxxxxxxxxx>
Date: Fri, 13 Jul 2007 19:01:46 +0100
RE:  XSLT 1.0 Stack Overflow Question
If your XSLT processor optimizes tail calls, you can make this
tail-recursive by changing it so that instead of comparing length(head) with
max-length(tail), you pass longest-so-far as a parameter on the recursive
call, and output its value when you get to the end. That way the result of
the recursive call doesn't need to be further processed by the caller, which
is what makes it a tail call.

Michael Kay
http://www.saxonica.com/


> -----Original Message-----
> From: Roger L. Cauvin [mailto:roger@xxxxxxxxxx] 
> Sent: 13 July 2007 18:40
> To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
> Subject:  XSLT 1.0 Stack Overflow Question
> 
> I'm parsing raw text (not XML or a node-set) that contains a 
> long list of items separated by linefeeds.  Let's say it's a 
> list of action items:
> 
>   Action Items
>   1. Ensure all tests pass.
>   2. Get sign-off on documentation from Amy.
>   3. Create a new page on web site for product.
>   4. Move product from staging area to production.
>   .
>   .
>   .
>   205. Send press release announcing release.
> 
> What I want to do is find the item with the greatest number 
> of characters in it.  So I have a recursive template:
> 
>   <xsl:template name="get-longest-item">
>     <xsl:param name="items"/>
>     <xsl:variable name="index">
>       <xsl:value-of select="substring-before(substring-after($items,
> '&#10;'), '.')"/>
>     </xsl:variable>
>     <xsl:choose>
>       <xsl:when test="$index = ''">
>         <xsl:text disable-output-escaping="yes">-1%-1</xsl:text>
>       </xsl:when>
>       <xsl:otherwise>
>         <xsl:variable name="item">
>           <xsl:value-of 
> select="substring-before(substring-after($items, '.
> '), '&#10;')"/>
>         </xsl:variable>
>         <xsl:variable name="length" select="string-length($item)"/>
>         <xsl:variable name="longest-of-rest">
>           <xsl:call-template name="get-longest-item">
>             <xsl:with-param name="items" 
> select="substring-after($items, '&#10;')" />
>           </xsl:call-template>
>         </xsl:variable>
>         <xsl:choose>
>           <xsl:when test="$length &gt; 
> substring-after($longest-of-rest, '%')">
>             <xsl:value-of select="concat($index, '%', $length)" />
>           </xsl:when>
>           <xsl:otherwise>
>             <xsl:value-of select="$longest-of-rest" />
>           </xsl:otherwise>
>         </xsl:choose>
>       </xsl:otherwise>
>     </xsl:choose>
>   </xsl:template>
> 
> The template "returns" the index of the longest item, 
> followed by the percent symbol, followed by the length of that item.
> 
> For a large list of action items, applying this template 
> results in a stack overflow.  A binary divide-and-conquer 
> approach would make much more efficient use of stack space, 
> but I can't figure out how to do it using XSLT 1.0.  I try to 
> cut the text into two halves, but doing so inevitably seems 
> to involve order N recursion.

Current Thread

PURCHASE STYLUS STUDIO ONLINE TODAY!

Purchasing Stylus Studio from our online shop is Easy, Secure and Value Priced!

Buy Stylus Studio Now

Download The World's Best XML IDE!

Accelerate XML development with our award-winning XML IDE - Download a free trial today!

Don't miss another message! Subscribe to this list today.
Email
First Name
Last Name
Company
Subscribe in XML format
RSS 2.0
Atom 0.3
Site Map | Privacy Policy | Terms of Use | Trademarks
Free Stylus Studio XML Training:
W3C Member
Stylus Studio® and DataDirect XQuery ™are products from DataDirect Technologies, is a registered trademark of Progress Software Corporation, in the U.S. and other countries. © 2004-2013 All Rights Reserved.