Question

I'm hard-coding the colspan value, but could I calculate it from the number of table cells in a row, e.g. using an xsl:variable?

The difficulty is in the fact, that the XML nodes contain more attributes than what I'm trying to show using the XSL, so I CANNOT reference the XML itself for counting. That's why I'm wondering if I can reference the html template inside the XSL instead.

Sample XML:

<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="xsl/allcompanies.xsl"?>
<Companies>
    <row Name="Company One" Address="Grote Markt 1" ZIP="1000" City="BRUSSEL" Country="BE" Telephone="02 261 05 55" Fax="" Email="" />
    <row Name="Company Two" Address="Tielweg 10" ZIP="2803 PK" City="Gouda" Country="NL" Telephone="" Fax="" Email=""/>
    <row Name="Company Three" Address="6 S.Millrock Drive" ZIP="UT 84121" City="Salt Lake City" Country="US" Telephone="+1 801 928 0000" Fax="" Email="" />
</Companies>

The XSL:

<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:template match="/">
    <html>
    <body>
    <table>
        <tr>
            <th colspan="6">Companies</th>
        </tr>
        <tr>
            <th>Name</th>
            <th>Address</th>
            <th>ZIP</th>
            <th>City</th>
            <th>Country</th>
            <th>Telephone</th>
        </tr>
        <xsl:for-each select="Companies/row">
        <tr>
            <td><xsl:value-of select="@Name"/></td>
            <td><xsl:value-of select="@Address"/></td>
            <td><xsl:value-of select="@ZIP"/></td>
            <td><xsl:value-of select="@City"/></td>
            <td><xsl:value-of select="@Country"/></td>
            <td><xsl:value-of select="@Telephone"/></td>
        </tr>
        </xsl:for-each>
    </table>
    </body>
    </html>
</xsl:template>
</xsl:transform>

I was thinking something along the lines of

<th colspan="{count(//table/tr[last()]/td)}">Companies</th>

but then something that, you know...works.

Knowing full well that what I'm trying here (setting a colspan) is, of course, trivial, I'm trying to poke at an underlying question, that of xslt applying XPath on itself.

Was it helpful?

Solution

You're not far off, but the expression must account for the structure of your input XML:

colspan="{count(//Companies/row[last()]/@*)}"

In your input XML, there are no table, tr and td elements.

I understand that you attempted to count the table cells that are being generated in your XSLT stylesheet, but this information can be retrieved from your input XML as well and it is more straightforward.


Besides, I am wondering why you'd like to count the number of cells dynamically in one place, if you hard-code the attributes that should be turned into table cells in another?

EDIT: It turns out that you intended to ask about the theoretical possibility of accessing nodes of the current stylesheet. Yes, there are ways to do this.

XSLT 1.0

If you are limited to XSLT 1.0, use the document() function, but without specifying an URI to be resolved:

<xsl:value-of select="count(document('')//td)"/>

Michael Kay's "XSLT 2.0 Programmer's Reference" says:

[document('')] refers to the stylesheet itself. This construct was often used with XSLT 1.0, where it provided a convenient way to maintain look-up tables in the stylesheet itself.

See for example this similar SO question.

XSLT 2.0

Store information about which attributes should be turned into table cells in an xsl:variable element. Then, access its contents both for generating the table and determining the value of the colspan attribute.

Actually, this could be done in XSLT 1.0 as well, if you have a means of converting a result tree fragment to a node-set (e.g. with an EXSLT function).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top