Hi,
I'm looking for an XSL-Stylesheet which normalizes complex
html-tables with col-span row-span to simple tables.
for example
___________
| |__|_____|
|__|__|__|__|
to
___________
|__|__|__|__|
|__|__|__|__|
I think someone had a similar problem two years ago, but he
got no solution. Subject was: Tranforming a table with
colspan and rowspan attributes to another more complex table
This is quite tricky... The rowspan causes most of the problems :)
Ive got a solution here that works first by sorting out the colspans,
then by processing the RTF produced from that vertically. The second
stage produces lots of <td>'s in the form:
<td row="1" col="1">.</td>
<td row="2" col="2">.</td>
<td row="1" col="2">.</td>
The final stage then outputs the table grouping the td's by row and
sorting by column number.
Apologies for the lack of comments/structure in the code, but it should
be pretty obvious from the variables copied to the output whats going
on.
So for this input:
<table border="1">
<tr>
<td colspan="2">.</td>
<td>.</td>
<td rowspan="3">.</td>
</tr>
<tr>
<td>.</td>
<td>.</td>
<td rowspan="2">.</td>
</tr>
<tr>
<td>.</td>
<td>.</td>
</tr>
</table>
With this stylesheet:
<?xml version="1.0"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:variable name="table_with_no_colspans">
<xsl:apply-templates mode="colspan"/>
</xsl:variable>
<xsl:variable name="table_with_no_rowspan">
<xsl:for-each select="$table_with_no_colspans">
<xsl:apply-templates mode="rowspan"/>
</xsl:for-each>
</xsl:variable>
<xsl:template match="@*|*" mode="colspan">
<xsl:copy>
<xsl:apply-templates select="@*|*" mode="colspan"/>
</xsl:copy>
</xsl:template>
<xsl:template match="td" mode="colspan">
<xsl:choose>
<xsl:when test="@colspan">
<xsl:call-template name="give_me_tds">
<xsl:with-param name="number-of-tds" select="@colspan"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<td><xsl:copy-of select="@*"/>.</td>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="give_me_tds">
<xsl:param name="number-of-tds"/>
<xsl:choose>
<xsl:when test="$number-of-tds > 1">
<td>.</td>
<xsl:call-template name="give_me_tds">
<xsl:with-param name="number-of-tds" select="$number-of-tds -
1"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<td>.</td>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="/">
<div>
<AAAAA><xsl:copy-of select="."/></AAAAA>
<XXXXX><xsl:copy-of select="$table_with_no_colspans"/></XXXXX>
<YYYYY><xsl:copy-of select="$table_with_no_rowspan"/></YYYYY>
<table border="1">
<xsl:for-each select="/table/tr">
<tr>
<xsl:variable name="pos" select="position()"/>
<xsl:apply-templates select="$table_with_no_rowspan/td[(_at_)row =
$pos]" mode="final">
<xsl:sort select="@col"/>
</xsl:apply-templates>
</tr>
</xsl:for-each>
</table>
</div>
</xsl:template>
<xsl:template match="td" mode="final">
<xsl:copy-of select="."/>
</xsl:template>
<xsl:template match="tr" mode="rowspan">
<xsl:apply-templates mode="rowspan">
<xsl:with-param name="rownum" select="position()"/>
</xsl:apply-templates>
</xsl:template>
<xsl:template match="td" mode="rowspan">
<xsl:param name="rownum"/>
<xsl:choose>
<xsl:when test="@rowspan">
<xsl:call-template name="rowspan_tds">
<xsl:with-param name="rowspan" select="@rowspan"/>
<xsl:with-param name="rownum" select="$rownum"/>
<xsl:with-param name="colnum"
select="count(preceding-sibling::td|.)"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<td row="{$rownum}" col="{count(preceding-sibling::td|.)}">.</td>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="rowspan_tds">
<xsl:param name="rowspan"/>
<xsl:param name="rownum"/>
<xsl:param name="colnum"/>
<xsl:choose>
<xsl:when test="$rowspan > 1">
<td row="{$rownum}" col="{$colnum}">.</td>
<xsl:call-template name="rowspan_tds">
<xsl:with-param name="rowspan" select="$rowspan - 1"/>
<xsl:with-param name="rownum" select="$rownum + 1"/>
<xsl:with-param name="colnum" select="$colnum"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<td row="{$rownum}" col="{$colnum}">.</td>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
Produces this output:
<?xml version="1.0" encoding="UTF-8"?>
<div>
<AAAAA>
<table border="1">
<tr>
<td colspan="2">.</td>
<td>.</td>
<td rowspan="3">.</td>
</tr>
<tr>
<td>.</td>
<td>.</td>
<td rowspan="2">.</td>
</tr>
<tr>
<td>.</td>
<td>.</td>
</tr>
</table>
</AAAAA>
<XXXXX>
<table border="1">
<tr>
<td>.</td>
<td>.</td>
<td>.</td>
<td rowspan="3">.</td>
</tr>
<tr>
<td>.</td>
<td>.</td>
<td rowspan="2">.</td>
</tr>
<tr>
<td>.</td>
<td>.</td>
</tr>
</table>
</XXXXX>
<YYYYY>
<td row="1" col="1">.</td>
<td row="1" col="2">.</td>
<td row="1" col="3">.</td>
<td row="1" col="4">.</td>
<td row="2" col="4">.</td>
<td row="3" col="4">.</td>
<td row="2" col="1">.</td>
<td row="2" col="2">.</td>
<td row="2" col="3">.</td>
<td row="3" col="3">.</td>
<td row="3" col="1">.</td>
<td row="3" col="2">.</td>
</YYYYY>
<table border="1">
<tr>
<td row="1" col="1">.</td>
<td row="1" col="2">.</td>
<td row="1" col="3">.</td>
<td row="1" col="4">.</td>
</tr>
<tr>
<td row="2" col="1">.</td>
<td row="2" col="2">.</td>
<td row="2" col="3">.</td>
<td row="2" col="4">.</td>
</tr>
<tr>
<td row="3" col="1">.</td>
<td row="3" col="2">.</td>
<td row="3" col="3">.</td>
<td row="3" col="4">.</td>
</tr>
</table>
</div>
cheers
andrew
XSL-List info and archive: http://www.mulberrytech.com/xsl/xsl-list