XSLT position() function not working as expected in Two Step View

1.2k Views Asked by At

While trying to implement the pattern "Two Step View" as described by Martin Fowler, I had some problems getting the alternate-row colouring of the HTML table to work. This uses the XSLT position() function. You can see the XSLT template for table/row below. However, in the output, the bgcolor attribute of the tr element is always "linen", indicating that the value of position() is not changing as we iterate over table/row elements. Why would this be?

<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
                xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:template match="screen">
    <html>
      <body bgcolor="white">
        <xsl:apply-templates/>
      </body>
    </html>
  </xsl:template>

  <xsl:template match="title">
    <h1>
      <xsl:apply-templates/>
    </h1>
  </xsl:template>

  <xsl:template match="field">
    <p><b><xsl:value-of select="@label"/>: </b><xsl:apply-templates/></p>
  </xsl:template>

  <xsl:template match="table">
    <table><xsl:apply-templates/></table>
  </xsl:template>

  <xsl:template match="table/row">
    <xsl:variable name="bgcolor">
      <xsl:choose>
        <xsl:when test="(position() mod 2) = 0">linen</xsl:when>
        <xsl:otherwise>white</xsl:otherwise>
      </xsl:choose>
    </xsl:variable>

    <tr bgcolor="{$bgcolor}"><xsl:apply-templates/></tr>
  </xsl:template>

  <xsl:template match="table/row/cell">
    <td><xsl:apply-templates/></td>
  </xsl:template>
</xsl:stylesheet>

Input XML:

<?xml version="1.0"?>
<screen>
  <title>Dissociation</title>
  <field label="Artist">Dillinger Escape Plan</field>
  <table>
    <row>
      <cell>Limerent Death</cell>
      <cell>4:06</cell>
    </row>
    <row>
      <cell>Symptom Of Terminal Illness</cell>
      <cell>4:03</cell>
    </row>
    <row>
      <cell>Wanting Not So Much To As To</cell>
      <cell>5:23</cell>
    </row>
  </table>
</screen>

Output HTML:

<html><body bgcolor="white">
  <h1>Dissociation</h1>
  <p><b>Artist: </b>Dillinger Escape Plan</p>
  <table>
    <tr bgcolor="linen">
      <td>Limerent Death</td>
      <td>4:06</td>
    </tr>
    <tr bgcolor="linen">
      <td>Symptom Of Terminal Illness</td>
      <td>4:03</td>
    </tr>
    <tr bgcolor="linen">
      <td>Wanting Not So Much To As To</td>
      <td>5:23</td>
    </tr>
  </table>
</body></html>
1

There are 1 best solutions below

3
On BEST ANSWER

Change <table><xsl:apply-templates/></table> to <table><xsl:apply-templates select="row"/></table> or use <xsl:strip-space elements="*"/> or at least <xsl:strip-space elements="table"/>. Currently you are processing all child nodes, including white space text nodes, that way your attempt using position() fails.