I want to create rows in a table dynamically depending on the content in the XML. In the below code I am trying to create a row(<tr>) with 5 columns. After 5 columns are filled, I want to create a new row.
A row can only contain 5 columns as per the below code. If i apply the XSL on the XML, I get an error displaying
XSLT compile error. The 'tr' start tag on line 574 does not match the end tag of 'xsl:when'. Line 578, position 7.
570:<table>
571: <xsl:for-each select="/alert/account_links/account_links_info">
572: <xsl:choose>
573: <xsl:when test="position() mod 5 = 1">
574: <tr>
575: <td>
576: <xsl:value-of select="account_id"/>
577: </td>
578: </xsl:when>
579: <xsl:when test="position() mod 5 = 0">
580: <td>
581: <xsl:value-of select="account_id"/>
582: </td>
583: </tr>
584: </xsl:when>
585: <xsl:otherwise>
586: <td>
587: <xsl:value-of select="account_id"/>
588: </td>
589: </xsl:otherwise>
590: </xsl:choose>
591: </xsl:for-each>
592: </table>
Input Xml:
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<alert>
<account_links>
<account_links_info>
<account_id>1</account_id>
</account_links_info>
<account_links_info>
<account_id>2</account_id>
</account_links_info>
<account_links_info>
<account_id>3</account_id>
</account_links_info>
<account_links_info>
<account_id>4</account_id>
</account_links_info>
<account_links_info>
<account_id>5</account_id>
</account_links_info>
</account_links>
</alert>
Can some one help me how to go ahead with this?
Try this solution:
<table>
<xsl:for-each select="/alert/account_links/account_links_info[position()mod5=1]">
<xsl:variable name = "current-pos" select="(position()-1) * 5+1"/>
<tr>
<xsl:for-each select="../account_links_info[position()>=$current-pos and position() < $current-pos+5]" >
<td>
<xsl:value-of select="account_id"/>
</td>
</xsl:for-each>
</tr>
</xsl:for-each>
</table>
(the idea is to have an outer loop for the <tr> output running through every fifth account_links_info element, and an inner loop filling the rows with the account_id values).
XSLT instructions produce nodes on a result tree, not lexical begin and end tags. Outputting a node is a single operation, you can't divide it into two operations writing half a node each. So your thinking should be "for every five nodes in the input I want to produce a node in the output", which leads naturally to a construct such as
<xsl:for-each select="*[position() mod 5 = 1]">
Don't be seduced into using disable-output-escaping for this. It's poison. It breaks the clean architectural boundary between the transformation engine and the serialized, which means that your stylesheet can't be cleanly deployed and reused in an arbitrary pipeline (which is the reason it won't work in Firefox, in case you're interested in the practical consequences).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With