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(_at_)MAIL(_dot_)ECU(_dot_)EDU]
Sent: Tuesday, April 13, 2004 1:40 PM
To: xsl-list(_at_)lists(_dot_)mulberrytech(_dot_)com
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
--+------------------------------------------------------------------
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list
To unsubscribe, go to: http://lists.mulberrytech.com/xsl-list/
or e-mail: <mailto:xsl-list-unsubscribe(_at_)lists(_dot_)mulberrytech(_dot_)com>
--+--