Click to See Complete Forum and Search --> : recursive templates in XSLT


monkeys3
04-15-2006, 03:35 PM
I am new to XSLT and am trying to grasp recursive templates. The "showbar" template should output a bar graph (red, blue or green) for the party affiliation based on the percent of votes. As my code is, I am getting no output and do not know what is missing in the recursive template or the template call.

<?xml version="1.0" ?>
<xsl:stylesheet version='1.0' xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="html" version="4.0" />

<xsl:variable name="redcell">
<td bgcolor="red" width="1"> </td>
</xsl:variable>

<xsl:variable name="bluecell">
<td bgcolor="blue" width="1"> </td>
</xsl:variable>

<xsl:variable name="greencell">
<td bgcolor="green" width="1"> </td>
</xsl:variable>

<xsl:template match="/">
<html>
<head>
<title>Election Night Results</title>
<link href="polls.css" rel="stylesheet" type="text/css" />
</head>
<body>
<h1>Election Night Results</h1>
<xsl:apply-templates select="polls/race" />
</body>
</html>
</xsl:template>

<xsl:template match="polls/race">
<h2><xsl:value-of select="title" /></h2>
<table cellpadding="3" cellspacing="0">
<xsl:apply-templates select="candidate" />

</table>
</xsl:template>

<xsl:template match="candidate">
<xsl:variable name="percent" select="format-number(votes div sum(..//votes), '#0%')"/>
<tr>
<td width="120"><xsl:value-of select="name" /> (<xsl:value-of select="party" />)</td>
<td width="80" align="right"><xsl:value-of select="format-number(votes, '#,##0') " /></td>
<td>(<xsl:copy-of select="$percent"/>)</td>
<td
<xsl:call-template name="showbar">
<xsl:with-param name="cells" select="$percent - 1"/>
<xsl:with-param name="party_type" select="party"/>
</xsl:call-template>
</td>
</tr>
</xsl:template>

<xsl:template name="showbar">
<xsl:param name="cells" select="0" />
<xsl:param name="party_type" select="party" />
<xsl:if test="$cells > 0">
<xsl:choose>
<xsl:when test="$party_type = 'R'"><xsl:copy-of select="$redcell"/></xsl:when>
<xsl:when test="$party_type = 'D'"><xsl:copy-of select="$bluecell"/></xsl:when>
<xsl:otherwise><xsl:copy-of select="$greencell"/></xsl:otherwise>
</xsl:choose>
<xsl:call-template name="showbar">
<xsl:with-param name="cells" select="$cells - 1"/>
<xsl:with-param name="party_type" select="$party_type"/>
</xsl:call-template>
</xsl:if>
</xsl:template>

</xsl:stylesheet>

Webnerd
04-18-2006, 08:36 AM
Try changing this:

<xsl:template match="polls/race">

to

<xsl:template match="race">

php_bob0325
04-21-2006, 11:52 AM
You're obviously using the same textbook I'm using.
Which, first off, is chocked full of typos, and there are 2 in this assignment that will throw you off. I just got my script to work.

First the 2 corrections:
page 7.69, #4 -- the little 'hint' is incorrect. It gives you: ../votes
when it should be: ..//votes

Looks like you got that right. Also, in #8, the last line says the 'color' paramater is used... etc. It should say, the 'party_type' parameter.

Webnerd's suggestion is correct. Make that change.

The problem, and it took me FOREVER to find it, is the percent variable in your candidate template. You can't format a variable, and then try to subtract one from it like you do here:

<xsl:with-param name="cells" select="$percent - 1"/>

First off, subtracting one is no good, you do that in the recursive template when you subtract one from the $cells variable. Following step #10, you should multiply the $percent variable by 100. So move the format-number function 4 lines down, so that this

(<xsl:copy-of select="$percent"/>)

becomes this:

<xsl:copy-of select="format-number($percent, '(#0%)')" />

and change this:

<xsl:variable name="percent" select="format-number(votes div sum(..//votes), '#0%')"/>

to just this:

<xsl:variable name="percent" select="votes div sum(..//votes)" />

That way, you can call your $percent variable and do whatever you want with it / to it.

Here is the full corrected candidate template.

<xsl:template match="candidate">
<xsl:variable name="percent" select="votes div sum(..//votes)" />
<tr>
<td width="120"><xsl:value-of select="name" /> (<xsl:value-of select="party" />)</td>
<td width="80" align="right">
<xsl:value-of select="format-number(votes, '#,##0')" />
<xsl:text> </xsl:text>
<xsl:copy-of select="format-number($percent, '(#0%)')" />
</td>
<xsl:call-template name="showbar">
<xsl:with-param name="cells" select="$percent * 100" />
<xsl:with-param name="party_type" select="party" />
</xsl:call-template>
</tr>
</xsl:template>

monkeys3
04-22-2006, 05:47 AM
Thank you php_bob0325!

Yes, this textbook has many typos. Your solution worked worked perfectly.