TonyC TonyC - 1 year ago 102
CSS Question

Using xsl to fill in empty rows in a html table

I want to create multiple html table pages using XML as the input and xsl as the transformation language.
Now these tables should always have a fixed height, whether it's just one row or ten.
I can't get it to work with CSS (min-height).
So I was wondering, if it is possible to get xsl to always output ten rows and add empty rows in case there are less then ten rows or adding rows in case there are more then ten rows existent in the XML and therefore resizing the table.

Any ideas how this can be achieved?

Answer Source

You sure can do that. I can show you how you would split your data into tables each having ten rows stuffing up the last one (or maybe the only one) with dummy rows when you don't have enough. It should help you get going where you need to go (without an example XML input and desired HTML output this is as much as I can do)

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html" encoding="UTF-8"/>

    <xsl:template match="/">
        <xsl:apply-templates select="data/row[position() mod 10 = 1]" mode="newtable"/>
    </xsl:template>

    <xsl:template match="row" mode="newtable">
        <table>
            <xsl:apply-templates select="."/>
            <xsl:apply-templates select="following-sibling::row[position() &lt; 10]"/>
            <xsl:call-template name="dummy-rows">
                <xsl:with-param 
                       name="how-many" 
                       select="9 - count(following-sibling::row[position() &lt; 10])"/>
            </xsl:call-template>
        </table>
    </xsl:template>

    <xsl:template match="row">
        <tr><td><xsl:value-of select="."/></td></tr>
    </xsl:template>

    <xsl:template name="dummy-rows">
        <xsl:param name="how-many" select="0"/>
        <xsl:if test="$how-many &gt; 0">
            <tr><td>dummy</td></tr>
            <xsl:call-template name="dummy-rows">
                <xsl:with-param name="how-many" select="$how-many - 1"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

The idea is that you start your table with the "first" node of each set of 10. That's the [position() mod 10 = 1] predicate. When you get a hold of the starting point of your table you create the table boundaries and process that node again in a normal mode. Then you get the next nine data rows that follow it. Finally, you add as many dummy nodes as you need to make sure you got the 10 total in each table. The dummy-rows template is a recursion. So two techniques here: splitting the set by position() mod and using a recursion to implement iteration.

UPDATE If you only need to make sure you have at least ten rows in your table then you don't need the split logic:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:output method="html" encoding="UTF-8"/>

    <xsl:template match="/">
        <table>
            <xsl:apply-templates select="data/row"/>
            <xsl:call-template name="dummy-rows">
                <xsl:with-param 
                    name="how-many" 
                    select="10 - count(data/row)"/>
            </xsl:call-template>
        </table>
    </xsl:template>

    <xsl:template match="row">
        <tr><td><xsl:value-of select="."/></td></tr>
    </xsl:template>

    <xsl:template name="dummy-rows">
        <xsl:param name="how-many" select="0"/>
        <xsl:if test="$how-many &gt; 0">
            <tr><td>dummy</td></tr>
            <xsl:call-template name="dummy-rows">
                <xsl:with-param name="how-many" select="$how-many - 1"/>
            </xsl:call-template>
        </xsl:if>
    </xsl:template>
</xsl:stylesheet>

You can try this with an input like this:

<data>
  <row>1</row>
  <row>1</row>
  <row>3</row>
</data>

or an input like this:

<data>
    <row>1</row>
    <row>2</row>
    <row>3</row>
    <row>4</row>
    <row>5</row>
    <row>6</row>
    <row>7</row>
    <row>8</row>
    <row>9</row>
    <row>10</row>
    <row>11</row>
    <row>12</row>
</data>

In both cases the result was as expected. Try it. You should be able to take it from here.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download