<article>
<table id="tbl1">
<caption><p>Table 1. Sample Table</p></caption>
<thead>
<tr>
<td colspan="3">I</td>
<td colspan="4">II</td>
</tr>
<tr>
<td>Sl. No.</td>
<td>Name</td>
<td>Place</td>
<td>Subject 1</td>
<td>Subject 2</td>
<td>Subject 3</td>
<td>Grade</td>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="3">1</td>
<td colspan="2">Kishan</td>
<td>95</td>
<td>96</td>
<td rowspan="2">97</td>
<td>A</td>
</tr>
<tr>
<td>Kishan</td>
<td>Bangalore</td>
<td>94</td>
<td>96</td>
<td>A</td>
</tr>
<tr>
<td>Likhith</td>
<td>Bhadravathi</td>
<td>94</td>
<td>94</td>
<td>99</td>
<td>A</td>
</tr>
</tbody>
</table>
</article>
必需OutPut:如果colspan是2在第二个单元格中编码,则第三个不应该在那里,下一个单元格名称应为“colname =”3“(起始索引为0)。对于rowspan,如果存在行的第一个单元格则相同如果rowspan =“3”,则接下来的两行不应该具有colname =“0”,接下来的两行起始单元格将具有名称=“1”(起始索引为0,这就是为什么1表示第二个单元格)。请建议对于XSLT编码,两个地址同时存在于同一个表中的rowspan和colspan。
<article>
<table id="tbl1">
<caption><p>Table 1. Sample Table</p></caption>
<thead>
<tr>
<td colname="0:0">I</td>
<td colname="0:3">II</td>
</tr>
<tr>
<td colname="1:0">Sl. No.</td>
<td colname="1:1">Name</td>
<td colname="1:2">Place</td>
<td colname="1:3">Subject 1</td>
<td colname="1:4">Subject 2</td>
<td colname="1:5">Subject 3</td>
<td colname="1:6">Grade</td>
</tr>
</thead>
<tbody>
<tr>
<td colname="2:0">1</td>
<td colname="2:1">Kishan</td>
<td colname="2:3">95</td>
<td colname="2:4">96</td>
<td colname="2:5">97</td>
<td colname="2:6">A</td>
</tr>
<tr>
<td colname="3:1">Kishan</td>
<td colname="3:2">Bangalore</td>
<td colname="3:3">94</td>
<td colname="3:4">96</td>
<td colname="3:6">A</td>
</tr>
<tr>
<td colname="4:1">Likhith</td>
<td colname="4:2">Bhadravathi</td>
<td colname="4:3">94</td>
<td colname="4:4">94</td>
<td colname="4:5">99</td>
<td colname="4:6">A</td>
</tr>
</tbody>
</table>
</article>
StackOverFlow站点的XSLT代码:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<!--rowspan in table with xslt-->
<xsl:template match="TABLE2">
<tbody>
<xsl:call-template name="processRows">
<xsl:with-param name="rows" select="ROW"/>
</xsl:call-template>
</tbody>
</xsl:template>
<xsl:template name="processRows">
<xsl:param name="rows"/>
<xsl:param name="index" select="1"/>
<!-- Bit vector for the columns -->
<xsl:param name="col1" select="0"/>
<xsl:param name="col2" select="0"/>
<xsl:param name="col3" select="0"/>
<xsl:param name="col4" select="0"/>
<xsl:param name="col5" select="0"/>
<xsl:param name="col6" select="0"/>
<xsl:variable name="cellsBefore2">
<xsl:choose>
<xsl:when test="$col1 > 0">0</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="cellsBefore3">
<xsl:choose>
<xsl:when test="$col2 > 0">
<xsl:value-of select="$cellsBefore2"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$cellsBefore2 + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="cellsBefore4">
<xsl:choose>
<xsl:when test="$col3 > 0">
<xsl:value-of select="$cellsBefore3"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$cellsBefore3 + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="cellsBefore5">
<xsl:choose>
<xsl:when test="$col4 > 0">
<xsl:value-of select="$cellsBefore4"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$cellsBefore4 + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="cellsBefore6">
<xsl:choose>
<xsl:when test="$col5 > 0">
<xsl:value-of select="$cellsBefore5"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$cellsBefore5 + 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<row>
<xsl:if test="$col1 = 0">
<entry colname="1">
<xsl:value-of select="$rows[$index]/CELL[1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col2 = 0">
<entry colname="2">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore2 + 1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col3 = 0">
<entry colname="3">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore3 + 1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col4 = 0">
<entry colname="4">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore4 + 1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col5 = 0">
<entry colname="5">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore5 + 1]/text()"/>
</entry>
</xsl:if>
<xsl:if test="$col6 = 0">
<entry colname="6">
<xsl:value-of select="$rows[$index]/CELL[$cellsBefore6 + 1]/text()"/>
</entry>
</xsl:if>
</row>
<xsl:if test="$index < count($rows)">
<xsl:call-template name="processRows">
<xsl:with-param name="rows" select="$rows"/>
<xsl:with-param name="index" select="$index + 1"/>
<xsl:with-param name="col1">
<xsl:choose>
<xsl:when test="$col1 > 0">
<xsl:value-of select="$col1 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[1]/@ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col2">
<xsl:choose>
<xsl:when test="$col2 > 0">
<xsl:value-of select="$col2 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore2 + 1]/@ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col3">
<xsl:choose>
<xsl:when test="$col3 > 0">
<xsl:value-of select="$col3 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore3 + 1]/@ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col4">
<xsl:choose>
<xsl:when test="$col4 > 0">
<xsl:value-of select="$col4 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore4 + 1]/@ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col5">
<xsl:choose>
<xsl:when test="$col5 > 0">
<xsl:value-of select="$col5 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore5 + 1]/@ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
<xsl:with-param name="col6">
<xsl:choose>
<xsl:when test="$col6 > 0">
<xsl:value-of select="$col6 - 1"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="number($rows[$index]/CELL[$cellsBefore6 + 1]/@ROWSPAN) - 1"/>
</xsl:otherwise>
</xsl:choose>
</xsl:with-param>
</xsl:call-template>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
答案 0 :(得分:6)
这一点都不简单。基本上,您正在询问如何通过将每个单元格定位在行等和列的(等间距)x-y网格上来呈现HTML表格直观。
这很复杂,因为每个单元格的位置不仅取决于同一行中前面单元格的宽度(colspan),还取决于前面行中跨越的单元格的位置不止一排。在处理前面的单元格之前,这个位置是未知的 - 所以这是一个巨大的渲染即用级联操作。
由于这种复杂性,我建议在引入其他约束之前首先单独解决基本问题(例如,单独的标题行或从0开始的数字)。
为了测试,我使用下表 1 作为输入:
<table border="1">
<tr>
<td>Column 1</td>
<td>Column 2</td>
<td>Column 3</td>
</tr>
<tr>
<td rowspan="2">A</td>
<td colspan="2">B</td>
</tr>
<tr>
<td>C</td>
<td>D</td>
</tr>
<tr>
<td>E</td>
<td rowspan="2" colspan="2">F</td>
</tr>
<tr>
<td>G</td>
</tr>
<tr>
<td colspan="3">H</td>
</tr>
</table>
应用以下样式表:
XSLT 1.0
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match="/table">
<table>
<xsl:text> </xsl:text>
<xsl:call-template name="generate-rows">
<xsl:with-param name="current-row" select="1"/>
<xsl:with-param name="last-row" select="count(tr)"/>
</xsl:call-template>
</table>
</xsl:template>
<xsl:template name="generate-rows">
<xsl:param name="current-row"/>
<xsl:param name="last-row"/>
<xsl:param name="result" select="some-dummy-node-to-make-this-a-node"/>
<!-- append current-row to previous result -->
<xsl:variable name="new-result">
<xsl:copy-of select="$result"/>
<row num="{$current-row}">
<xsl:text> </xsl:text>
<!-- generate cells for current-row -->
<xsl:call-template name="generate-cells">
<xsl:with-param name="current-row" select="$current-row"/>
<xsl:with-param name="current-cell" select="1"/>
<xsl:with-param name="x" select="1"/>
<xsl:with-param name="last-cell" select="count(tr[$current-row]/td)"/>
<xsl:with-param name="previous-rows" select="$result"/>
</xsl:call-template>
</row>
<xsl:text> </xsl:text>
</xsl:variable>
<xsl:choose>
<xsl:when test="$current-row < $last-row">
<!-- recursive call -->
<xsl:call-template name="generate-rows">
<xsl:with-param name="current-row" select="$current-row + 1"/>
<xsl:with-param name="last-row" select="$last-row"/>
<xsl:with-param name="result" select="$new-result"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<!-- return result -->
<xsl:copy-of select="$new-result"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template name="generate-cells">
<xsl:param name="current-row"/>
<xsl:param name="current-cell"/>
<xsl:param name="x"/>
<xsl:param name="last-cell"/>
<xsl:param name="previous-rows"/>
<xsl:variable name="my-cell" select="tr[$current-row]/td[$current-cell]" />
<xsl:choose>
<!-- if there's a collision, move one place to the right -->
<xsl:when test="exsl:node-set($previous-rows)/row/cell[@x <= $x and @x + @width > $x and @y + @height > $current-row]">
<xsl:call-template name="generate-cells">
<xsl:with-param name="current-row" select="$current-row"/>
<xsl:with-param name="current-cell" select="$current-cell"/>
<xsl:with-param name="x" select="$x + 1"/>
<xsl:with-param name="last-cell" select="$last-cell"/>
<xsl:with-param name="previous-rows" select="$previous-rows"/>
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:variable name="width">
<xsl:choose>
<xsl:when test="$my-cell/@colspan">
<xsl:value-of select="$my-cell/@colspan"/>
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:variable name="height">
<xsl:choose>
<xsl:when test="$my-cell/@rowspan">
<xsl:value-of select="$my-cell/@rowspan"/>
</xsl:when>
<xsl:otherwise>1</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<xsl:text>	</xsl:text>
<cell num="{$current-cell}" y="{$current-row}" x="{$x}" width="{$width}" height="{$height}">
<xsl:value-of select="$my-cell"/>
</cell>
<xsl:text> </xsl:text>
<xsl:if test="$current-cell < $last-cell">
<xsl:call-template name="generate-cells">
<xsl:with-param name="current-row" select="$current-row"/>
<xsl:with-param name="current-cell" select="$current-cell + 1"/>
<xsl:with-param name="x" select="$x + $width"/>
<xsl:with-param name="last-cell" select="count(tr[$current-row]/td)"/>
<xsl:with-param name="previous-rows" select="$previous-rows"/>
</xsl:call-template>
</xsl:if>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
</xsl:stylesheet>
生成以下结果:
<?xml version="1.0" encoding="UTF-8"?>
<table>
<row num="1">
<cell num="1" y="1" x="1" width="1" height="1">Column 1</cell>
<cell num="2" y="1" x="2" width="1" height="1">Column 2</cell>
<cell num="3" y="1" x="3" width="1" height="1">Column 3</cell>
</row>
<row num="2">
<cell num="1" y="2" x="1" width="1" height="2">A</cell>
<cell num="2" y="2" x="2" width="2" height="1">B</cell>
</row>
<row num="3">
<cell num="1" y="3" x="2" width="1" height="1">C</cell>
<cell num="2" y="3" x="3" width="1" height="1">D</cell>
</row>
<row num="4">
<cell num="1" y="4" x="1" width="1" height="1">E</cell>
<cell num="2" y="4" x="2" width="2" height="2">F</cell>
</row>
<row num="5">
<cell num="1" y="5" x="1" width="1" height="1">G</cell>
</row>
<row num="6">
<cell num="1" y="6" x="1" width="3" height="1">H</cell>
</row>
</table>
如您所见,每个单元格的x-y定位对应于浏览器中原始表格的可视化渲染:
-
1.来自http://en.wikipedia.org/wiki/Help:Table
对于 XSLT 2.0 :
将样式表声明更改为:
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
将第66行更改为:
<xsl:when test="$previous-rows/row/cell[@x <= $x and @x + @width > $x and @y + @height > $current-row]">