Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generating multiple dynamic rows of html table using XSLT

Tags:

xml

xslt

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?

like image 725
RVK Avatar asked Mar 06 '26 09:03

RVK


2 Answers

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()&gt;=$current-pos and position() &lt; $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).

like image 79
Doc Brown Avatar answered Mar 08 '26 20:03

Doc Brown


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).

like image 20
Michael Kay Avatar answered Mar 08 '26 20:03

Michael Kay