php dom文档删除一些html标签但保留内部标签和文本

时间:2014-01-27 11:11:10

标签: php html tags domdocument

我需要删除HTML文档中的一些标记(例如<div></div>)并保留内部标记和文本。 我设法用Simple HTML Dom Parser做到了。但由于存储器需求巨大,它无法处理大文件。 我更喜欢使用像DOMDocument这样的原生PHP工具,因为我读到它在处理HTML文档时更加优化和快捷。 但是我在第一阶段挣扎 - 如何在保留内部文本和标签的同时删除一些标签。

源HTML示例是:

<html><body><div>00000</div>aaaaa<div>bbbbbb<div>ccc<a>link</a>ccc</div>dddddd</div>eeeee<div>1111</div></body></html>

我试试这段代码:

$htmltext='<html><body><div>00000</div>aaaaa<div>bbbbbb<div>ccc<a>link</a>ccc</div>dddddd</div>eeeee<div>1111</div></body></html>';
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTML($htmltext);
$oldnodes = $doc->getElementsByTagName('div');
foreach ($oldnodes as $node) {
    $fragment = $doc->createDocumentFragment();
    while($node->childNodes->length > 0) {
        $fragment->appendChild($node->childNodes->item(0));
    }
    $node->parentNode->replaceChild($fragment, $node);
}
echo $doc->saveHTML();

它产生输出:

<html><body>00000aaaaa<div>bbbbbbccc<a>link</a>cccdddddd</div>eeeee<div>1111</div></body></html>

我需要以下内容:

<html><body>00000aaaaabbbbbbccc<a>link</a>cccddddddeeeee1111</body></html>

有人可以帮我解决任务的正确代码吗?

4 个答案:

答案 0 :(得分:1)

您可以在PHP中使用strip_tags函数。

$thmltext = '<html><body><div>00000</div>aaaaa<div>bbbbbb<div>ccc<a>link</a>ccc</div>dddddd</div>eeeee<div>1111</div></body></html>';
strip_tags($htmltext, '<html>,<body>,<a>');

除去 html,body,a

之外,删除所有标签

输出是:

<html><body>00000aaaaabbbbbbccc<a>link</a>cccddddddeeeee1111</body></html>

修改 如果是来自用户的输入,出于安全原因使用白名单标签而不是黑名单会更好。

答案 1 :(得分:0)

如果您的代码只包含没有任何属性的简单HTML标记,则可以保持简单,如:

$value = '<html><body><div>00000</div>aaaaa<div>bbbbbb<div>ccc<a>link</a>ccc</div>dddddd</div>eeeee<div>1111</div></body></html>';
$pattern = '/<[\/]*(div|h1)>/';

$removedTags = preg_replace($pattern, '', $value);

由于您在评论中写道,除了要删除的div标签之外,我还在模式中添加了一个h1标签,以防您想要删除h1标签。

此代码段仅适用于简单代码,但适合您的HTML输入和输出示例。

答案 2 :(得分:0)

试试这个.. 只需使用以下代码替换for循环即可。

foreach ($oldnodes as $node) {
    $children = $node->childNodes;
    $string = "";
    foreach($children as $child) {
        $childString = $doc->saveXML($child);
        $string = $string."".$childString;
    }
    $fragment = $doc->createDocumentFragment();
    $fragment->appendXML($string);
    $node->parentNode->insertBefore($fragment,$node);
    $node->parentNode->removeChild($node);
}

答案 3 :(得分:0)

我找到了让它发挥作用的方法。 有问题的原因代码是在nodelist ruin nodelist中使用节点进行操作。所以“foreach”函数只通过nodelist中的4个项目中的2个 - 其余2个变得扭曲。

所以我只需要处理列表的第一个元素,然后重建列表,直到列表中有一些项目为止。

代码是:

$htmltext='<html><body><div>00000</div>aaaaa<div>bbbbbb<div>ccc<a>link</a>ccc</div>dddddd</div>eeeee<div>1111</div></body></html>';
echo "<!-- 
".$htmltext."
-->
";
libxml_use_internal_errors(true);
$doc = new DOMDocument();
$doc->loadHTML($htmltext);
$oldnodes = $doc->getElementsByTagName('div');
while ($oldnodes->length>0){
    $node=$oldnodes->item(0);
    $fragment = $doc->createDocumentFragment();
    while($node->childNodes->length > 0) {
        $fragment->appendChild($node->childNodes->item(0));
    }
    $node->parentNode->replaceChild($fragment, $node);
    $oldnodes = $doc->getElementsByTagName('div');
}
echo $doc->saveHTML();

我希望这会对遇到同样困难的人有所帮助。