Jump to content

Xsl Recursion Force Quit


Recommended Posts

Hi all, I have a problem with xsl and recursions..My input is a html file, I use xsl 1.0. My goal is to sum up fields (<td>) from a html table if a condition is true. The problem: The function calls itself after it was at the xsl:otherwise statement (please look at totalPackages function) E.g. I have 10 fields where on three fields the conditions fits(<xsl:if test = "number($bweight[$i]) = '0'" > <xsl:if test = "number($nweight[$i]) = '0'" >)The sum should be e.g. 10 + 6 + 12 = 28 As result I get = 28282828 After debugging with xml spy I found out that the recursion calls itself after the xsl:otherwise statement, I don't get it, after the otherwise statement and no call:template statement the function should be finished.. Has someone an idea? here is my code :

<xsl:template name="totalPackages">  <xsl:param name="summe" select="0"/>  <xsl:param name="amount"  />  <xsl:param name="bweight" />  <xsl:param name="nweight" />  <xsl:param name="i" select="1" />   <xsl:choose>    <xsl:when test="$bweight[$i]"> 	<xsl:if test = "number($bweight[$i]) = '0'" >	 <xsl:if test = "number($nweight[$i]) = '0'" >	  	  <xsl:call-template name="totalPackages">	   <xsl:with-param name="summe" select="number($summe) + number($amount[$i])" />	   <xsl:with-param name="i" select="$i + 1" />	   <xsl:with-param name="bweight" select="$bweight" />	   <xsl:with-param name="nweight" select="$nweight" />	   <xsl:with-param name="amount" select="$amount" />	  </xsl:call-template>	  	 </xsl:if>	</xsl:if> 	<xsl:if test = "number($bweight[$i]) > '0'" >		 <xsl:call-template name="totalPackages">	  <xsl:with-param name="summe" select="number($summe)" />	  <xsl:with-param name="i" select="$i + 1" />	  <xsl:with-param name="bweight" select="$bweight" />	  <xsl:with-param name="nweight" select="$nweight" />	  <xsl:with-param name="amount" select="$amount" />	 </xsl:call-template>		</xsl:if> 	<xsl:if test = "number($nweight[$i]) > '0'" >		 <xsl:call-template name="totalPackages">	  <xsl:with-param name="summe" select="number($summe)" />	  <xsl:with-param name="i" select="$i + 1" />	  <xsl:with-param name="bweight" select="$bweight" />	  <xsl:with-param name="nweight" select="$nweight" />	  <xsl:with-param name="amount" select="$amount" />	 </xsl:call-template>		</xsl:if>	     </xsl:when>    <xsl:otherwise>	<xsl:value-of select="$summe" />   </xsl:otherwise>   </xsl:choose></xsl:template>

<td>	<b>	 <xsl:call-template name="totalPackages">	  <xsl:with-param name="amount" select="//tr/td[@id = 'amount']" />	  <xsl:with-param name="bweight" select="//tr/td[@id = 'bweight']" />	  <xsl:with-param name="nweight" select="//tr/td[@id = 'nweight']" />	 </xsl:call-template>	</b>   </td>

Edited by Den-J
  • Like 2
Link to post
Share on other sites

The input but like pseudo code:

<html><head><title>Hi world !</title></head><body><form name="Form1" method="post"  action="some stuff"  id="Form1">  <p></p>  <table width="900px" cellspacing="2" cellpadding="1" border="0">   <tr>    <td id="1" width="40px">a ball</td>    <td id="2" width="40px">a pin</td>    <td id="3" width="*">a sword</td>    <td id="4" width="*"> </td>    <!--some comment-->    <!--some comment-->    <!--some comment-->    <td id="amount" width="75px" class="r">6</td>    <td id="5" width="75px" class="r">a date like 11.07.2001</td>    <!--some comment-->    <!--some comment-->    <td id="6" width="75px">378_</td>    <!--some comment-->    <!--some comment-->    <!--some comment-->    <td id="bweight" width="*">0</td>    <td id="nweight" width="*">0</td>    <td id="7" width="*">0</td>   </tr>     <tr>    The same stuff like before with other data   </tr>     <tr>    The same stuff like before with other data   </tr>     <tr>    The same stuff like before with other data   </tr>     <tr>    The same stuff like before with other data   </tr>     <tr>    The same stuff like before with other data   </tr>  </table>  <p></p></form></body></html>

Link to post
Share on other sites
When reading your XSLT code it looks as if you simply call your template several times in all those xsl: if branches.
Well yes, I do recursion because I cannot do a for loop with xsl like
for i = 1; last element of bweight ; i++	 do that and thatend loop

I want to count the amount node when bweight and nweight is zero. I have a counter $i for accessing each node like in a for loop

Link to post
Share on other sites

So I took your samples trying to create a test case to reproduce the problem, the XML input sample is the one you posted i.e.

<html><head><title>Hi world !</title></head><body><form name="Form1" method="post"  action="some stuff"  id="Form1">  <p></p>  <table width="900px" cellspacing="2" cellpadding="1" border="0">   <tr>    <td id="1" width="40px">a ball</td>    <td id="2" width="40px">a pin</td>    <td id="3" width="*">a sword</td>    <td id="4" width="*"> </td>    <!--some comment-->    <!--some comment-->    <!--some comment-->    <td id="amount" width="75px" class="r">6</td>    <td id="5" width="75px" class="r">a date like 11.07.2001</td>    <!--some comment-->    <!--some comment-->    <td id="6" width="75px">378_</td>    <!--some comment-->    <!--some comment-->    <!--some comment-->    <td id="bweight" width="*">0</td>    <td id="nweight" width="*">0</td>    <td id="7" width="*">0</td>   </tr>    <tr>    The same stuff like before with other data   </tr>    <tr>    The same stuff like before with other data   </tr>    <tr>    The same stuff like before with other data   </tr>    <tr>    The same stuff like before with other data   </tr>    <tr>    The same stuff like before with other data   </tr>  </table>  <p></p></form></body></html>

then I created a minimal stylesheet with your named template and its call:

<xsl:stylesheet  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"  version="1.0"> <xsl:template name="totalPackages">  <xsl:param name="summe" select="0"/>  <xsl:param name="amount"  />  <xsl:param name="bweight" />  <xsl:param name="nweight" />  <xsl:param name="i" select="1" />   <xsl:choose>    <xsl:when test="$bweight[$i]"> 	    <xsl:if test = "number($bweight[$i]) = '0'" >		 <xsl:if test = "number($nweight[$i]) = '0'" >		  		  <xsl:call-template name="totalPackages">		   <xsl:with-param name="summe" select="number($summe) + number($amount[$i])" />		   <xsl:with-param name="i" select="$i + 1" />		   <xsl:with-param name="bweight" select="$bweight" />		   <xsl:with-param name="nweight" select="$nweight" />		   <xsl:with-param name="amount" select="$amount" />		  </xsl:call-template>		  		 </xsl:if>	    </xsl:if> 	    <xsl:if test = "number($bweight[$i]) > '0'" >	    		 <xsl:call-template name="totalPackages">		  <xsl:with-param name="summe" select="number($summe)" />		  <xsl:with-param name="i" select="$i + 1" />		  <xsl:with-param name="bweight" select="$bweight" />		  <xsl:with-param name="nweight" select="$nweight" />		  <xsl:with-param name="amount" select="$amount" />		 </xsl:call-template>	    	    </xsl:if> 	    <xsl:if test = "number($nweight[$i]) > '0'" >	    		 <xsl:call-template name="totalPackages">		  <xsl:with-param name="summe" select="number($summe)" />		  <xsl:with-param name="i" select="$i + 1" />		  <xsl:with-param name="bweight" select="$bweight" />		  <xsl:with-param name="nweight" select="$nweight" />		  <xsl:with-param name="amount" select="$amount" />		 </xsl:call-template>	    	    </xsl:if>	        </xsl:when>    <xsl:otherwise>	    <xsl:value-of select="$summe" />   </xsl:otherwise>   </xsl:choose></xsl:template><xsl:template match="/"><xsl:call-template name="totalPackages">		  <xsl:with-param name="amount" select="//tr/td[@id = 'amount']" />		  <xsl:with-param name="bweight" select="//tr/td[@id = 'bweight']" />		  <xsl:with-param name="nweight" select="//tr/td[@id = 'nweight']" />		 </xsl:call-template></xsl:template></xsl:stylesheet>

When I use Saxon 6.5.5 to apply the stylesheet to the sample document I get the output

<?xml version="1.0" encoding="utf-8"?>6

So at least with that input sample I am not able to see a wrong result, you should post minimal samples to allow us to reproduce the problem. As a wild guess however I wonder whether you really need a named template, can't you simply do e.g.

<xsl:value-of select="sum(//tr[td[@id = 'bweight'] = 0 and td[@id = 'nweight'] = 0]/td[@id = 'amount'])"/>

? That would be my XPath representation of your English description "I want to count the amount node when bweight and nweight is zero".

Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...