HTML::Query 如何在 perl 5 中自动完成无效 HTML?
How HTML::Query autocomplete invalid HTML in perl 5?
我有无效的 HTML
代码,在 thead
中缺少 tr
。尽管如此,我正在尝试使用 HTML::Query
select 这个 HTML
的元素,但是 select 或有违反直觉的行为。
这是我的代码:
#!/usr/bin/env perl
require HTML::Query;
use JSON;
my $q = HTML::Query->new( text => '
<table>
<thead>
<th>A</th>
<th>B</th>
<th>C</th>
</thead>
<tbody>
<tr>
<td>E</td>
<td>F</td>
<td>G</td>
</tr>
</tbody>
</table>
' );
my %data = (
tr => $q->query('tr')->first->as_trimmed_text,
tbody => $q->query('tbody')->first->as_trimmed_text
);
print JSON->new->utf8(0)->encode( \%data );
结果:
{
"tbody": "",
"tr": "BC"
}
当然,如果我使用正确的 HTML
代码但缺少 tr
:
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
</tr>
</thead>
<tbody>
<tr>
<td>E</td>
<td>F</td>
<td>G</td>
</tr>
</tbody>
</table>
然后程序打印疑似直观输出:
{
"tr": "ABC",
"tbody": "EFG"
}
我的问题:
- 为什么第一个字母
A
被省略了?
- 为什么
tbody
找不到?
- 如何
HTML::Query
处理无效HTML
?它是固定的吗?哪种方式?
我找到了部分答案。添加到散列 %data
对:
html => $q->as_HTML
我可以看到无效 HTML
这个结果:
<html>
<head></head>
<body>
<table>
<thead></thead>
<th>A</th>
<tr>
<th>B</th>
<th>C</th>
<tbody></tbody>
</tr>
<tr>
<td>E</td>
<td>F</td>
<td>G</td>
</tr>
</table>
</body>
</html>
所以我知道无效HTML
是如何转换的
在我看来,它是可以改变的。 Link 创建问题:
我是这个包的维护者。
HTML::Query 在 HTML::Tree 提供的解析功能之上提供了选择器魔法。 HTML::Query 本身不提供解析。您的问题出在 HTML::Tree,而不是 HTML::Query.
HTML:树在很大程度上早于规范一致性。它最初是在 IE 统治互联网 (1999) 并根据 "real world" 用法处理 HTML 时创建的。它在处理 HTML 4 个文档方面做得很好,但是正如您所注意到的,非常规标记存在一些问题,这些标记在 HTML 4 中是合法的。没有办法处理这些边缘情况,库不能也不会处理它们,因为有成千上万的组织依赖现有的实施来继续像以前一样工作。
HTML::Tree 不正确支持 HTML5。底层库的作者 HTML::TagSet 拒绝支持它,并与任何提供解决方案或提出接管库的人争论(或忽略)。这种立场有效地阻止了所有衍生项目正确处理 HTML5 - HTML::Query 和 CSS::Inliner 也不例外。
至于建议使用 HTML::HTML5::Parser 或 "whatever other Perl modules that provide an HTML parser" - 我欢迎补丁。话虽这么说:没有充分维护的 Perl 库可以为 table 带来 HTML::Tree 所做的事情,因此任何此类尝试都可能会失败,但让我们看看您能想出什么。
我有无效的 HTML
代码,在 thead
中缺少 tr
。尽管如此,我正在尝试使用 HTML::Query
select 这个 HTML
的元素,但是 select 或有违反直觉的行为。
这是我的代码:
#!/usr/bin/env perl
require HTML::Query;
use JSON;
my $q = HTML::Query->new( text => '
<table>
<thead>
<th>A</th>
<th>B</th>
<th>C</th>
</thead>
<tbody>
<tr>
<td>E</td>
<td>F</td>
<td>G</td>
</tr>
</tbody>
</table>
' );
my %data = (
tr => $q->query('tr')->first->as_trimmed_text,
tbody => $q->query('tbody')->first->as_trimmed_text
);
print JSON->new->utf8(0)->encode( \%data );
结果:
{
"tbody": "",
"tr": "BC"
}
当然,如果我使用正确的 HTML
代码但缺少 tr
:
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>C</th>
</tr>
</thead>
<tbody>
<tr>
<td>E</td>
<td>F</td>
<td>G</td>
</tr>
</tbody>
</table>
然后程序打印疑似直观输出:
{
"tr": "ABC",
"tbody": "EFG"
}
我的问题:
- 为什么第一个字母
A
被省略了? - 为什么
tbody
找不到? - 如何
HTML::Query
处理无效HTML
?它是固定的吗?哪种方式?
我找到了部分答案。添加到散列 %data
对:
html => $q->as_HTML
我可以看到无效 HTML
这个结果:
<html>
<head></head>
<body>
<table>
<thead></thead>
<th>A</th>
<tr>
<th>B</th>
<th>C</th>
<tbody></tbody>
</tr>
<tr>
<td>E</td>
<td>F</td>
<td>G</td>
</tr>
</table>
</body>
</html>
所以我知道无效HTML
是如何转换的
在我看来,它是可以改变的。 Link 创建问题:
我是这个包的维护者。
HTML::Query 在 HTML::Tree 提供的解析功能之上提供了选择器魔法。 HTML::Query 本身不提供解析。您的问题出在 HTML::Tree,而不是 HTML::Query.
HTML:树在很大程度上早于规范一致性。它最初是在 IE 统治互联网 (1999) 并根据 "real world" 用法处理 HTML 时创建的。它在处理 HTML 4 个文档方面做得很好,但是正如您所注意到的,非常规标记存在一些问题,这些标记在 HTML 4 中是合法的。没有办法处理这些边缘情况,库不能也不会处理它们,因为有成千上万的组织依赖现有的实施来继续像以前一样工作。
HTML::Tree 不正确支持 HTML5。底层库的作者 HTML::TagSet 拒绝支持它,并与任何提供解决方案或提出接管库的人争论(或忽略)。这种立场有效地阻止了所有衍生项目正确处理 HTML5 - HTML::Query 和 CSS::Inliner 也不例外。
至于建议使用 HTML::HTML5::Parser 或 "whatever other Perl modules that provide an HTML parser" - 我欢迎补丁。话虽这么说:没有充分维护的 Perl 库可以为 table 带来 HTML::Tree 所做的事情,因此任何此类尝试都可能会失败,但让我们看看您能想出什么。