7

我正在尝试在 php 中使用 DOMDocument::loadHTML 编辑 html 标签。html 数据是 html 的一部分,而不是整个页面。我遵循了这个页面(PHP - DOMDocument - 需要更改/替换现有的 HTML 标签 w/新标签)所说的内容。

这应该将 pre 标签转换为 div 标签,但它会给出“致命错误:未捕获的异常 'DOMException' 和消息'未找到错误'。”

<?php
$contents = <<<STR
<pre>hi</pre>
<pre>hello</pre>
<pre>bye</pre>
STR;

$dom = new DOMDocument;
@$dom->loadHTML($contents);

foreach( $dom->getElementsByTagName("pre") as $nodePre ) {
    $nodeDiv = $dom->createElement("div", $nodePre->nodeValue);
    $dom->replaceChild($nodeDiv, $nodePre);
}

echo $dom->saveHTML();
?>

[编辑]当我尝试向后迭代节点对象时,我收到此错误,“注意:尝试获取非对象的属性...”

<?php
$contents = <<<STR
<pre>hi</pre>
<pre>hello</pre>
<pre>bye</pre>
STR;

$dom = new DOMDocument;
@$dom->loadHTML($contents);
$domPre = $dom->getElementsByTagName('pre');
$length = $domPre->length;

    For ($i = $length; $i > -1 ; $i--) {
        $nodePre = $domPre->item($i);
        echo $nodePre->nodeValue . '<br />';
//      $nodeDiv = $dom->createElement("div", $nodePre->nodeValue);
//      $dom->replaceChild($nodeDiv, $nodePre);
    }

    // echo $dom->saveHTML();
?>

[编辑] 好的,解决了。由于回答的代码有一些错误,我在这里发布了解决方案。谢谢大家。

解决方案:

<?php
$contents = <<<STR
<pre>hi</pre>
<pre>hello</pre>
<pre>bye</pre>
STR;

$dom = new DOMDocument;
@$dom->loadHTML($contents);
$domPre = $dom->getElementsByTagName('pre');
$length = $domPre->length;

For ($i = $length - 1; $i > -1 ; $i--) {
    $nodePre = $domPre->item($i);
    $nodeDiv = $dom->createElement("div", $nodePre->nodeValue);
    $nodePre->parentNode->replaceChild($nodeDiv, $nodePre);
}

echo $dom->saveHTML();
?>
4

2 回答 2

16

问题是调用replaceChild(). 而不是

$dom->replaceChild($nodeDiv, $nodePre);

利用

$nodePre->parentNode->replaceChild($nodeDiv, $nodePre);

更新

这是一个工作代码。替换多个节点似乎存在一些问题(更多信息在这里: http: //php.net/manual/en/domnode.replacechild.php)所以你必须使用回归循环来替换元素。

$contents = <<<STR
<pre>hi</pre>
<pre>hello</pre>
<pre>bye</pre>
STR;

$dom = new DOMDocument;
@$dom->loadHTML($contents);

$elements = $dom->getElementsByTagName("pre");
for ($i = $elements->length - 1; $i >= 0; $i --) {
    $nodePre = $elements->item($i);
    $nodeDiv = $dom->createElement("div", $nodePre->nodeValue);
    $nodePre->parentNode->replaceChild($nodeDiv, $nodePre);
}
于 2012-08-18T13:04:20.637 回答
3

使用paquettg/php-html-parser 的另一种方法(没有找到更改名称的方法,因此不得不使用 hack 和 re-binding $this):

use PHPHtmlParser\Dom;
use PHPHtmlParser\Dom\HtmlNode;

$dom = new Dom;
$dom->load($text);
/** @var HtmlNode[] $tags */
foreach($dom->find('pre') as $tag) {
    $changeTag = function() {
        $this->name = 'div';
    };
    $changeTag->call($tag->tag);
};
echo (string)$dom;
于 2017-08-30T16:49:01.320 回答