Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Westi on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

XSL - add to a variable in a loop

Status
Not open for further replies.

MrPeds

Programmer
Jan 7, 2003
219
GB
Hi,

Is it possible to increase the value of a xsl variable in a stylesheet whilst i am looping around some elements?

What I mean is if i do something like declare a variable:
<xsl:variable name="myVar"/>

Can i reference this in my loop and add to it, e.g. by adding the value of another variable e.g. in pseudo code:

myVar = myVar + $anothervariable

All i basically want to do is add up some values as i go along to display a total at the bottom of an HTML table row.

Any ideas?

Regards.

MrPeds
 
No, you cannot do what you are requesting.

However, if you think in terms of nodesets, you can use the XPath function sum which returns the sum of all the nodes passed as parameters. So, something like [tt]<xsl:value-of select="sum(./quantity)" />[/tt] will return the sum of all quantity elements immediately subordinate to the context element.

When in XSL, think in terms of aggregate functions over nodesets, such as sum, and also think in terms of recursion to solve problems you might use looping for in other languages.

Tom Morrison
 
I think i will have to assign the totals using client side JavaScript.

Each value that I would want to sum is in fact the result of a calculation whilst looping through elements, so it would not be possible to use sum in this case i guess.

I think i read somewhere that you can set up a template to accept some paramaters and return a value that way to set up a counter?

MrPeds
 
I think i read somewhere that you can set up a template to accept some paramaters

Yes, you can do this. Have a look here for some examples of recursion. You can take the techniques shown and modify for your use.

I my opinion, it would be far easier to use a recursive algorithm on the server side (at the point where you want to create the calculated total) rather than do JavaScript, but this may be a result of my bias against JavaScript.

Tom Morrison
 
Here is an example of using recursion for this type of problem.

Example data
Code:
<?xml version="1.0"?>
<exampleData>
  <cylinder>
	<a-val>2</a-val>
	<b-val>5</b-val>
  </cylinder>
  <cylinder>
	<a-val>4</a-val>
	<b-val>5</b-val>
  </cylinder>
  <cylinder>
	<a-val>4</a-val>
	<b-val>10</b-val>
  </cylinder>
  <cylinder>
	<a-val>1</a-val>
	<b-val>1</b-val>
  </cylinder>
</exampleData>

XSLT (stylesheet)
Code:
<xsl:stylesheet version="1.0" xmlns:xsl="[URL unfurl="true"]http://www.w3.org/1999/XSL/Transform">[/URL]
  <xsl:output method="html"/>
  <xsl:template match="/">
    <xsl:variable name="totalVolume">
      <xsl:call-template name="ComputeTotalVolume">
        <xsl:with-param name="nodeList" select="exampleData/cylinder"/>
        <xsl:with-param name="totalSoFar" select="0"/>
      </xsl:call-template>
    </xsl:variable>
    <html>
      <body>
        <table>
          <tr>
            <td>A</td>
            <td>B</td>
            <td>PI * (0.5*A)**2 * B</td>
          </tr>
          <xsl:for-each select="exampleData/cylinder">
            <xsl:variable name="radius" select="number(a-val) * 0.5"/>
            <tr>
              <td>
                <xsl:value-of select="a-val"/>
              </td>
              <td>
                <xsl:value-of select="b-val"/>
              </td>
              <td>
                <xsl:value-of select="3.14159 * $radius * $radius * number(b-val)"/>
              </td>
            </tr>
          </xsl:for-each>
        </table>
        <br/>
        <xsl:text>Total = </xsl:text>
        <xsl:value-of select="$totalVolume"/>
        <br/>
      </body>
    </html>
  </xsl:template>

  <xsl:template name="ComputeTotalVolume">
    <xsl:param name="nodeList"/>
    <xsl:param name="totalSoFar"/>
    <xsl:choose>
      <xsl:when test="$nodeList">
        <!-- if there is still a node in the list -->
        <xsl:variable name="remainingNodes" select="$nodeList[position() != 1]"/>
        <xsl:variable name="radius" select="0.5 * number($nodeList[1]/a-val)"/>
        <xsl:variable name="volumeIncludingThisNode" select="$totalSoFar + (3.14159 * $radius * $radius * number($nodeList[1]/b-val))"/>
        <xsl:call-template name="ComputeTotalVolume">
          <xsl:with-param name="nodeList" select="$remainingNodes"/>
          <xsl:with-param name="totalSoFar" select="$volumeIncludingThisNode"/>
        </xsl:call-template>
      </xsl:when>
      <xsl:otherwise>
        <!-- return the computed value -->
        <xsl:value-of select="$totalSoFar"/>
      </xsl:otherwise>
    </xsl:choose>
  </xsl:template>
</xsl:stylesheet>

Output
Code:
<html>
	<body>
		<table>
			<tr>
				<td>A</td>
				<td>B</td>
				<td>PI * (0.5*A)**2 * B</td>
			</tr>
			<tr>
				<td>2</td>
				<td>5</td>
				<td>15.70795</td>
			</tr>
			<tr>
				<td>4</td>
				<td>5</td>
				<td>62.8318</td>
			</tr>
			<tr>
				<td>4</td>
				<td>10</td>
				<td>125.6636</td>
			</tr>
			<tr>
				<td>1</td>
				<td>1</td>
				<td>0.7853975</td>
			</tr>
		</table>
		<br/>Total = 204.9887475<br/></body>
</html>
[small]It has been years since solid geometry.

Tom Morrison
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top