This is the mail archive of the xsl-list@mulberrytech.com mailing list .


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: Table generation with XSL?


The following stylesheet should do what you want (and
does with Saxon 5.3.2). Obviously there are some
optimisations possible - all of "match"ed templates
could be moved into the root template, for instance -
but I separated it out for clarity. Sorry, no
documentation, but I think it's pretty clear what's
going on - the key thing to note is that you have
to use recursion to implement counting functionality
in XSLT.

<?xml version="1.0" encoding="UTF-8"?>

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                version="1.0">

<xsl:output method="xml" indent="yes" />

<xsl:template match="Table">
  <xsl:variable name="num_columns">
    <xsl:call-template name="count_columns" />
  </xsl:variable>

  <table>
    <xsl:apply-templates select="HeadRow">
      <xsl:with-param name="num_columns" select="$num_columns" />
    </xsl:apply-templates>
    <xsl:apply-templates select="Row">
      <xsl:with-param name="num_columns" select="$num_columns" />
    </xsl:apply-templates>
    <xsl:apply-templates select="Caption">
      <xsl:with-param name="num_columns" select="$num_columns" />
    </xsl:apply-templates>
  </table>
</xsl:template>


<xsl:template name="count_columns">
  <xsl:param name="num_columns" select="'0'" />
  <xsl:param name="num_rows"    select="count(HeadRow) + count(Row)" />
  <xsl:param name="current_row" select="1" />

  <xsl:choose>
    <xsl:when test="$current_row &lt; $num_rows">
      <xsl:variable name="row" select="(HeadRow | Row)[$current_row]" />
      <xsl:choose>
        <xsl:when test="count($row/Cell) &gt; $num_columns">
          <xsl:call-template name="count_columns">
            <xsl:with-param name="num_columns" select="count($row/Cell)" />
            <xsl:with-param name="num_rows"    select="$num_rows" />
            <xsl:with-param name="current_row" select="$current_row + 1" />
          </xsl:call-template>
        </xsl:when>
        <xsl:otherwise>
          <xsl:call-template name="count_columns">
            <xsl:with-param name="num_columns" select="$num_columns" />
            <xsl:with-param name="num_rows"    select="$num_rows" />
            <xsl:with-param name="current_row" select="$current_row + 1" />
          </xsl:call-template>
        </xsl:otherwise>
      </xsl:choose>
    </xsl:when>
    <xsl:otherwise>
      <xsl:value-of select="$num_columns" />
    </xsl:otherwise>
  </xsl:choose>
</xsl:template>


<xsl:template match="HeadRow">
  <xsl:param name="num_columns" />

  <thead>
    <tr>
      <xsl:for-each select="Cell">
        <td><xsl:copy-of select="*|text()" /></td>
      </xsl:for-each>
      <xsl:call-template name="insert_blank_cells">
        <xsl:with-param name="num_cells" select="$num_columns - count(Cell)" />
      </xsl:call-template>
    </tr>
  </thead>
</xsl:template>


<xsl:template match="Row">
  <xsl:param name="num_columns" />

  <tr>
    <xsl:for-each select="Cell">
      <td><xsl:copy-of select="*|text()" /></td>
    </xsl:for-each>
    <xsl:call-template name="insert_blank_cells">
      <xsl:with-param name="num_cells" select="$num_columns - count(Cell)" />
    </xsl:call-template>
  </tr>
</xsl:template>


<xsl:template match="Caption">
  <xsl:param name="num_columns" />

  <tr>
    <td colspan="{$num_columns}"><xsl:copy-of select="*|text()" /></td>
  </tr>
</xsl:template>


<xsl:template name="insert_blank_cells">
  <xsl:param name="num_cells" />

  <xsl:if test="$num_cells &gt; 0">
    <td><xsl:value-of select="'&#160;'" /></td>
    <xsl:call-template name="insert_blank_cells">
      <xsl:with-param name="num_cells" select="$num_cells - 1" />
    </xsl:call-template>
  </xsl:if>
</xsl:template>


</xsl:stylesheet>


-- 
Warren Hedley
Department of Engineering Science
Auckland University
New Zealand


 XSL-List info and archive:  http://www.mulberrytech.com/xsl/xsl-list

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]