我正在编写一个工具,将HTML表格转换为CSV,我注意到一些奇怪的行为.根据这个代码,

$html = <<<HTML
<table>
<tr><td>A</td><td>Rose</td></tr>
</table>

<h1>Leave me behind</h1>

<table>
<tr><td>By</td><td>Any</td></tr>
</table>

<table>
<tr><td>Other</td><td>Name</td></tr>
</table>
HTML;

$dom = new \DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);

foreach ($dom->getElementsByTagName('table') as $table) {
    foreach ($table->getElementsByTagName('tr') as $row) {
        echo trim($row->nodeValue) . PHP_EOL;
    }
}

我希望输出如下:

ARose
ByAny
OtherName

但我得到的是:

ARose
ByAny
OtherName
ByAny
OtherName

如果我省略第一个结束标记,我会得到相同的结果.看起来DOMDocument将第二个和第三个<table>嵌套在第一个中.

事实上,如果我使用xpath只从每个表中获取直接子项,我会得到正确的输出:

$xpath = new \DOMXPath($dom);

foreach ($dom->getElementsByTagName('table') as $table) {
    foreach ($xpath->query('./tr', $table) as $row) {
        echo trim($row->nodeValue) . PHP_EOL;
    }
}

推荐答案

<body></body>将您的$html括起来

修改代码(注:我注释掉了$stream行)

<?php
$html = <<<HTML
<body>
<table>
<tr><td>A</td><td>Rose</td></tr>
</table>

<h1>Leave me behind</h1>

<table>
<tr><td>By</td><td>Any</td></tr>
</table>

<table>
<tr><td>Other</td><td>Name</td></tr>
</table>
</body>
HTML;

$dom = new \DOMDocument();
$dom->loadHTML($html, LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);

$tables = $dom->getElementsByTagName('table');
// $stream = \fopen('php://output', 'w+');

for ($i = 0; $i < $tables->length; ++$i) {
    $rows = $tables->item($i)->getElementsByTagName('tr');

    for ($j = 0; $j < $rows->length; ++$j) {
        echo trim($rows->item($j)->nodeValue) . "<br><br>";
    }
}

// fclose($stream);
?>

或者,改变

$dom->loadHTML($html, LIBXML_HTML_NODEFDTD | LIBXML_HTML_NOIMPLIED);

$dom->loadHTML($html, LIBXML_HTML_NODEFDTD);

Php相关问答推荐

如何在搜索域名时重定向到登陆页?

Laravel数据表在一个视图中传递两个实例

Sylius php -如何将购物车传递到小枝模板(Sylius模板事件)

在冲突和几何上插入的Postgres参数化查询在PHP中不起作用

有没有可能从composer 过时的输出中隐藏不需要的主要版本?

带Redhat php curl的http_code 0

模仿GUZLE中的curl 工作脚本(分块数据和二进制上传一起)

如何在自定义邮箱内容中获取WooCommerce订单项目的详细信息?

批量更新 WooCommerce 中所有产品的特定自定义字段

为什么 debug_backtrace() 不返回任何内容?

在特征中使用类的属性

CodeIgniter 4中嵌套过滤器组不起作用

在wordpress注销后防止后退操作

显示时间范围内的可用空位,同时考虑已预订的空位

我试图在我的视图上显示从数据库中获取的数据,但我无法显示它.拉维尔 10.x /

PHP 日期格式:ISO8601 与 ISO8601_EXPANDED

每个发布请求 Laravel 9 的 CSRF 令牌不匹配

列表不在 GROUP BY 子句中并且包含 X2CRM 中的非聚合列

图像不会显示在生产中的 Laravel 应用程序中

PHP获取根据辞职日期自动续订的合同终止日期