Wrox Programmer Forums
Go Back   Wrox Programmer Forums > XML > XSLT
| Search | Today's Posts | Mark Forums Read
XSLT General questions and answers about XSLT. For issues strictly specific to the book XSLT 1.1 Programmers Reference, please post to that forum instead.
Welcome to the p2p.wrox.com Forums.

You are currently viewing the XSLT section of the Wrox Programmer to Programmer discussions. This is a community of software programmers and website developers including Wrox book authors and readers. New member registration was closed in 2019. New posts were shut off and the site was archived into this static format as of October 1, 2020. If you require technical support for a Wrox book please contact http://hub.wiley.com
 
Old December 16th, 2006, 12:55 PM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default TEMPLATE CALCULATION

Hi,

Note: I use XSLT 1.0 and MSXML

When I run the template below passing number 3 as the argument, I was very very surprised by the result. In fact, I was so surprised I decide to ask for help to understand what is going.

The $n parameter will be 3 first time. Then I test to see if it is not a 1. While it is not a 1, I call the template again subtracting 1 from $n ($n-1). When $n equals 1 then I set the value of $ns variable to 1.

When I output the result like this:

<xsl:value-of select="$ns * $n"/>

I thought I would get a 1 since the last time through the recursion the value of parameter $n is 1 and the value of the variable $ns is also 1.

But I got a 6 !!!!!!!!

It seems to me that <xsl:value-of select="$ns * $n"/> keeps track of the previous values of $ns and $n during the recursion and multiply them instead. This bit is executed 3 times even though it is outside the recursion!!!

Am I going mad or there is something different about recursion in XSLT that I need to understand?

Cheers

<xsl:template name="Calculation">
<xsl:param name="n"/>
<xsl:variable name="ns">
 <xsl:choose>
  <xsl:when test="$n=1">1</xsl:when>
  <xsl:otherwise>
    <xsl:call-template name="Calculation">
      <xsl:with-param name="n" select="$n - 1"/>
    </xsl:call-template>
  </xsl:otherwise>
 </xsl:choose>
</xsl:variable>


<xsl:value-of select="$ns * $n"/>

</xsl:template>
 
Old December 16th, 2006, 03:30 PM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Your <xsl:value-of> instruction is being executed every time the template is called, what makes you think it should only be executed the last time?

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old December 17th, 2006, 03:12 PM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Michael,

Thanks for your reply. Michael, this is really really strange. If I cannot figure out what is going on here I think I do not understand anything about XSLT!!

Here is how I am calling the template. Please note that I call it only once and then inside the template I use recursion.

While $n is not 1 I use recursion to subtract one from $n. Then it jumps to this bit <xsl:value-of select="$ns * $n"/>. I can see in the watch window in this order the following:

1 x 1
1 x 2
2 x 3 = 6 and that is what I get.

<xsl:variable name="StartNumber" select="3"/>

<xsl:template match="/">
 <xsl:call-template name="Calculation">
   <xsl:with-param name="n" select="$StartNumber"/>
 </xsl:call-template>
</xsl:template>

<xsl:template name="Calculation">
<xsl:param name="n"/>
<xsl:variable name="ns">
 <xsl:choose>
  <xsl:when test="$n=1">1</xsl:when>
  <xsl:otherwise>
    <xsl:call-template name="Calculation">
      <xsl:with-param name="n" select="$n - 1"/>
    </xsl:call-template>
  </xsl:otherwise>
 </xsl:choose>
</xsl:variable>


<xsl:value-of select="$ns * $n"/>

</xsl:template>


Cheers,

CPall
 
Old December 18th, 2006, 05:45 AM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Your template is called once "from the outside", and twice by means of recursive calls. The xsl:value-of within the template is not in any kind of conditional, therefore it is executed each time the template is called, that is, thrice.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old December 20th, 2006, 12:40 PM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Michael,

Thanks for you explanation.

I think I can see what is going on now. I did not realise that since the xsl:value-of is not in any kind of conditional, that it would be executed each time the template is called and in reverse order.

Cheers,

CPall
 
Old December 21st, 2006, 12:35 PM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Michael,

I just have one final question about this topic.

1 - Since xsl:value-of is executed each time the template is called (that is three times), shouldn`t it output three results (one for each call) ??

2 - Also, why is it executed in reverse order ? Shouldn`t it not excute the call from outside first and then the calls from inside the recursion ?

Like this:

2 x 3
1 x 2
1 x 1

and output 6 then 2 then 1 ???

Cheers,

CPall
 
Old December 21st, 2006, 02:14 PM
mhkay's Avatar
Wrox Author
Points: 18,487, Level: 59
Points: 18,487, Level: 59 Points: 18,487, Level: 59 Points: 18,487, Level: 59
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Apr 2004
Location: Reading, Berks, United Kingdom.
Posts: 4,962
Thanks: 0
Thanked 292 Times in 287 Posts
Default

Try something more simple like this:

<xsl:template name="x">
  <xsl:param name="count"/>
  <xsl:if test="$count > 0">
    <xsl:call-template name="x">
      <xsl:with-param name="count" select="$count - 1"/>
    </xsl:call-template>
  </xsl:if>
  [<xsl:value-of select="$count"/>]
</xsl:template>

<xsl:template match="/">
    <xsl:call-template name="x">
      <xsl:with-param name="count" select="3"/>
    </xsl:call-template>
</xsl:template>

What should happen is this:

x is called with count = 3
  x is called with count = 2
    x is called with count = 1
      x is called with count = 0
      output [0]
    output [1]
  output [2]
output [3]

Does this make it any more clear? The values are output in reverse order because the template outputs the value after the recursive call returns.

If it's still not clear, imagine replacing template x by several templates x0, x1, x2, x3.

Michael Kay
http://www.saxonica.com/
Author, XSLT Programmer's Reference and XPath 2.0 Programmer's Reference
 
Old December 22nd, 2006, 07:20 PM
Friend of Wrox
Points: 1,243, Level: 13
Points: 1,243, Level: 13 Points: 1,243, Level: 13 Points: 1,243, Level: 13
Activity: 0%
Activity: 0% Activity: 0% Activity: 0%
 
Join Date: Oct 2003
Location: , , United Kingdom.
Posts: 290
Thanks: 24
Thanked 0 Times in 0 Posts
Default

Hi Michael,

Thanks for your help and example. I will try the example and see if I can understand it better.

After your previous explantion everytying is clearer. The only thing that I still need to think I bit more about is why it outputs only one value and not all of them since the xsl:value-of is executed 3 times. But I have not debug your example yet to see what happens.

I would like to take the opportunity to wish you and everyone in this forum a Merry Christmans and Happy New Year.

Cheers,

CPall




Similar Threads
Thread Thread Starter Forum Replies Last Post
Global parameter calculation inside template Volder XSLT 8 June 20th, 2008 08:10 AM
Age Calculation rgerald SQL Server 2000 32 October 10th, 2007 01:12 AM
Calculation in asp mateenmohd Classic ASP Basics 4 May 2nd, 2005 03:11 AM
Calculation with two averages mushu SQL Language 7 September 29th, 2004 09:50 AM
Calculation Grantm Access 3 February 16th, 2004 10:14 AM





Powered by vBulletin®
Copyright ©2000 - 2020, Jelsoft Enterprises Ltd.
Copyright (c) 2020 John Wiley & Sons, Inc.