RE: [xsl] converting empty nodes to col/rowspan values

Subject: RE: [xsl] converting empty nodes to col/rowspan values
From: "Josh Canfield" <Josh.Canfield@xxxxxxxxxxxx>
Date: Tue, 13 Apr 2004 14:30:45 -0700
The key is picking the empty cells before the next occupied cell, and after the current cell. You can do this using the following-sibling, and preceding-sibling axis' like this:

  <xsl:variable name="the-cell" select="."/>
  <xsl:variable name="num-joined" select="
              count(following-sibling::cell[ .='' and 
                      (generate-id(preceding-sibling::cell[not(.='')][1]) = generate-id($the-cell))
                    ])"/>

following-sibling::cell[.=''] selects only cells with no text content

preceding-sibling::cell[not(.='')][1] selects the nearest preceding sibling that has text content

Use generate-id to ensure that you are comparing the correct node, and not the node value.

Put it all together and get something like this:

<xsl:stylesheet version="1.0"
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform";>
	<xsl:output method="xml" indent="yes" encoding="utf-8"/>

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

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

<xsl:template match="row">
  <tr>
  <!-- apply templates only to those that are not empty, or if they are the first empty -->
    <xsl:apply-templates select="cell[not(preceding-sibling::cell) or not(.='')]"/>
  </tr>
</xsl:template>

<xsl:template match="cell">
  <xsl:variable name="the-cell" select="."/>
  <xsl:variable name="num-joined" select="
              count(following-sibling::cell[ .='' and 
                      (generate-id(preceding-sibling::cell[not(.='')][1]) = generate-id($the-cell))
                    ])"/>
  <td>
  <xsl:if test="$num-joined">
    <xsl:attribute name="colspan">
      <xsl:value-of select="$num-joined + 1"/>
    </xsl:attribute>
  </xsl:if>
    <xsl:value-of select="."/>
  </td>
</xsl:template>

</xsl:stylesheet>


Josh

-----Original Message-----
From: Reece, Michael Clark [mailto:REECEM@xxxxxxxxxxxx]
Sent: Tuesday, April 13, 2004 1:40 PM
To: xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Subject: [xsl] converting empty nodes to col/rowspan values


I am try to format an html with colspan and rowspan values for empty nodes.
For example with:
 
<?xml version="1.0"?>
<table>
  <row>
    <cell>Sample Table</cell>
    <cell></cell>
    <cell></cell>
    <cell></cell>
    <cell></cell>
  </row>
  <row>
    <cell>A</cell>
    <cell>B</cell>
    <cell></cell>
    <cell>C</cell>
    <cell></cell>
  </row>
  <row>
    <cell></cell>
    <cell>D</cell>
    <cell>E</cell>
    <cell>F</cell>
    <cell>G</cell>
  </row>
  <row>
    <cell>H</cell>
    <cell>I</cell>
    <cell>J</cell>
    <cell>K</cell>
    <cell></cell>
  </row>
</table>
 
I want the first row to be:
  <tr><td colspan=5>Sample Table</td></tr>
And the second row to be:
  <tr><td rowspan=2>A</td><td colspan=2>B</td><td colspan=2>C</td></tr>
 
And so forth...
 
This is my template:
 
<?xml version='1.0'?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform
<http://www.w3.org/1999/XSL/Transform> ">
<xsl:template match="/">
      <html>
      <table border="1">
      <xsl:apply-templates/>
      </table>
      </html>
</xsl:template>
<xsl:template match="table">
      <xsl:for-each select="row">
            <tr><xsl:apply-templates/></tr>
      </xsl:for-each>
</xsl:template>
<xsl:template match="cell">
      <td><xsl:value-of select="."/></td>
</xsl:template>
</xsl:stylesheet>
 
I have tried many iterations but cannot figure this out.  Thanks...
 
Michael Reece

Current Thread