Click to See Complete Forum and Search --> : Dynamic XSLT Iterations


tomhartland
05-14-2007, 09:11 AM
Hi :)

Don't know if "dynamic XSLT iterations" is the right description, but I couldn't think what else to call it.

I'm attempting to create an HTML table using XSLT, where the number of columns is dependant on the data.
An example of the data will hopefully make it clearer, where the number of scores is variable, therefore all the "scoreX" nodes will be created as required by the data provider.
<root>
<config>
<numscores>3</numscores>
<config>
<data>
<name>Adam</name>
<score1>1</score1>
<score2>2</score2>
<score3>3</score3>
</data>
<data>
<name>Bill</name>
<score1>2</score1>
<score2>4</score2>
<score3>5</score3>
</data>
</root>
This is the HTML I would like to get back out from the XSLT, but I cannot work out how to loop (in this case) 3 times to find "score1", "score2" and "score3"...

<table>
<tr>
<td>Name</td>
<td>Score 1</td>
<td>Score 2</td>
<td>Score 3</td>
</tr>
<tr>
<td>Adam</td>
<td>1</td>
<td>2</td>
<td>3</td>
</tr>
<tr>
<td>Bill</td>
<td>2</td>
<td>4</td>
<td>6</td>
</tr>
<table>

Any help or ideas would be appreciated,
Cheers,
Tom :)

jkmyoung
05-16-2007, 05:45 PM
This will give you something pretty close, the difference being the heading row. Seperated into 2 for-each loops. One for getting the headings, the other for actually getting the data.

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:fo="http://www.w3.org/1999/XSL/Format">
<xsl:template match="/root">
<table>
<!-- heading row -->
<tr>
<xsl:for-each select="data[1]/*">
<td>
<xsl:value-of select="name()"/>
</td>
</xsl:for-each>
</tr>
<xsl:apply-templates select="data"/>
<!-- data rows -->
</table>
</xsl:template>
<xsl:template match="data">
<tr>
<xsl:for-each select="*">
<td>
<xsl:value-of select="."/>
</td>
</xsl:for-each>
</tr>
</xsl:template>
</xsl:stylesheet>

tomhartland
05-16-2007, 06:04 PM
This will give you something pretty close, the difference being the heading row. Seperated into 2 for-each loops. One for getting the headings, the other for actually getting the data.
Thanks for the reply, but it's not quite what I was after.

Fortunately I've found solution (via another forum), and this is it.
Hope it helps somebody else...
<xsl:variable name="numQuestions" select="/root/config/numscores"/>
...
<xsl:for-each select="root/data">
<xsl:call-template name="GetScores">
<xsl:with-param name="scoreCount" select="1"/>
<xsl:with-param name="header" select="0"/>
</xsl:call-template>
</xsl:template>
...
<xsl:template name="GetScores">
<xsl:param name="scoreCount"/>
<xsl:param name="header"/>
<xsl:if test="$scoreCount &lt;= $numQuestions">
<xsl:variable name="scoreVal">
<xsl:for-each select="*">
<xsl:if test="name(.) = concat('score' , $scoreCount)">
<xsl:value-of select="."/>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<td>
<xsl:choose>
<xsl:when test="$header=1">
<strong><xsl:value-of select="$scoreCount"/></strong>
</xsl:when>
<xsl:when test="$scoreVal!=''>
<xsl:value-of select="$scoreVal"/>
</xsl:when>
<xsl:otherwise>&amp;#160;</xsl:otherwise>
</xsl:choose>
</td>
<xsl:call-template name="GetScores">
<xsl:with-param name="scoreCount"><xsl:value-of select="$scoreCount + 1"/></xsl:with-param>
<xsl:with-param name="header"><xsl:value-of select="$header"/></xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>