我需要解析一个包含colspans和rowspans的HTML表格并构建它的表示。
阅读HTML不是问题,我使用HTMLCleaner和XQuery与Saxon(Java)。
但我正在寻找一个很好的算法来构建表格,因为我不理解浏览器遵循的规则"困难"例。
例如,给定下表(rowspan错误的地方)
<table border=1>
<tr><td rowspan="3">1</td><td>2</td></tr>
<tr><td>3</td></tr>
</table>
我应用以下算法:
1) for each tr
1.1) expand the colspan and rowspan of the cells in the current line
1.2) create a new line if it doesn't already exist
1.3) for each td add the elements to the line
即。 (E是一个空单元格)
newline->no line existing==no expansion
add line elements (1.3)
line1: 1 [tr=3], 2
newline->tr expansion (1.1)
line1: 1[tr=3], 2
line2: E
line3: E
add line elements (1.3)
line1: 1[tr=3], 2
line2: E, 3
line3: E
必须删除第3行(Firefox只渲染两行),我怎么知道?
我特别感兴趣的是,不完整线条的元素与下列元素的元素完成,例如:
<tr><td>1</td><td>2</td><td>3</td></tr>
<tr><td>4</td><td>5</td></tr>
<tr><td>6</td></tr>
rendering: 1 2 3
4 5 6
我有一个实际案例:this file包含两个TR,即使它们是两个不同的TR,它们也会呈现为一个。为什么?
它们被渲染为(在红色矩形内)
如何决定将元素排入上一行?
对于奇怪的代码,浏览器遵循哪些规则?
我使用Java,我也理解javascript和一些PHP,但我我主要对算法感兴趣。我想知道某些事情是否存在或听到任何建议。
我想要的是能够输出表格的文本表示,就像真实浏览器呈现的一样。
修改:
在我读到xtratic回答之后,我读了HTML table processing model specification,但它似乎没有回答我关于何时必须将元素排列到前一行的问题,就像我描述的实际情况一样(和在此编辑中添加)。实际上,文档说&#34; 16如果当前单元格是正在处理的tr元素中的最后一个td或th元素子元素,则将ycurrent增加1,中止这组步骤,并返回上面的算法。&#34 ;。但并不总是发生在找到最后一个td时我们去一个新行。
我更感兴趣的是何时合并不同的行。当前一行的TD数量少于已发现的最大值时,我试图将TD排在上一行之后,但它不起作用
答案 0 :(得分:1)
阅读 HTML table processing model specification ,了解有关如何处理HTML表格的所有信息。 (它不容易)
由于您要解析html表的形式,我建议您按照 §4.9.12.1 Forming a table 中列出的步骤编写处理器(步骤18进入处理行)。我很确定浏览器也是这样做的。这些步骤以尽可能方便的方式编写,以便转换为处理器的代码,因此您应该能够非常简单地遵循它。处理器完成后,您应该有一个单元格表(如定义的那样),然后您可以使用现有的表格模型执行任何操作。我不能保证这很容易,但至少你会有一步一步的指导。
要更加明确:没有&#34;组合行&#34;但是有些单元格跨越多行。
algorithm for growing downward是将GENERALI SPA..
放在所有这些行的开头,并将来自以下<tr>
元素的数据添加到各自行的下一个可用单元格中。< / p>
GENERALI SPA...
跨越4行,但它的第一行是隐藏的,因为它上面没有其他数据,所以它看起来只有3行。
<tr> <!-- row 1 (0px high) -->
<!-- td spans from [1,1] to [1,4] -->
<!-- this fills the first column of rows 1, 2, 3, and 4 -->
<td rowspan="4">GENERALI SPA #1</td>
</tr>
<tr> <!-- row 2 -->
<!-- col 1 is taken by the cell defined above -->
<!-- td spans from [2,2] to [2,3] taking up col 2 of row 2 and 3 -->
<td rowspan="2">GENERALI SPA #2</td>
<td>Proprieta'</td> <!-- ... -->
</tr>
<tr> <!-- row 3 -->
<!-- col 1 and 2 are taken by the cells defined above -->
<td rowspan="1">Totale #1</td> <!-- ... -->
</tr>
<tr> <!-- row 4 -->
<!-- col 1 is taken by the cell defined above -->
<td colspan="2">Totale #2</td> <!-- ... -->
</tr>
没有格式化或隐藏的表格如下所示:
1 2 3 4
+----------------------+---------------------+-------------+---
1 | ... | (implied) (implied) <-- 0px high (hidden)
+- -+---------------------+-------------+---
2 | "GENERALI SPA #1" | "GENERALI SPA #2" | "Proprieta" | ..
+- -+- -+-------------+---
3 | ... | ... | "Totale #1" | ..
+- -+---------------------+-------------+---
4 | ... | "Totale #2" ... | ..
+----------------------+---------------------+-------------+---
这基本上是通过遵循html规范中的过程解析后获得的表模型。
我没有注意到删除&#34;不完整&#34;行(定义不完整),让它们留在表中,它们本质上是在它们包含的更多数据之前的标题行,并且它们不会真正伤害任何东西,你可以很容易地检测到它们。
但是,如果您真的想要,那么您可以删除除了跨越其他行的单元格之外没有明确创建的单元格的行。对于上面的表部分,您可以删除第1行,因为第1列跨越行1,2,3和4,而第1行没有其他显式创建的单元格。因此,第1行的所有数据仍然存在于数据跨越的单元格中[[[1,2],[1,3],[1,4]),您可以安全地删除第1行。
作为一个额外的例子,当我将rowspan
更改为1时,此数据会显示在其自己的行中,并且以下<tr>
数据会填充各自行中的可用单元格:
vvv 不太相关的信息 vvv
年龄较大的HTML 4.01 Specification,有一个与您的问题相关的直接示例:
下一个示例说明(在表格边框的帮助下)跨越多个行或列的单元格定义如何影响后续单元格的定义。请考虑以下表定义:
<TABLE border="1">
<TR><TD>1 <TD rowspan="2">2 <TD>3
<TR><TD>4 <TD>6
<TR><TD>7 <TD>8 <TD>9
</TABLE>
作为细胞&#34; 2&#34;跨越第一行和第二行,第二行的定义将考虑它。因此,第二行中的第二TD实际上定义了行的第三个单元。在视觉上,该表可能会被渲染为tty设备:
-------------
| 1 | 2 | 3 |
----| |----
| 4 | | 6 |
----|---|----
| 7 | 8 | 9 |
-------------
请注意,如果TD定义单元格&#34; 6&#34;如果已省略,则用户代理将添加一个额外的空单元格以完成该行。
这个related question and answer列出了一些可以帮助你抓桌子的图书馆,但是我不相信这个答案可以解决这个困难的问题。因为它假设<td>
元素的出现与表中的单元格索引完全对应。