我有以下HTML代码与自定义标记<gcse:search>
。它来自"自定义谷歌搜索引擎"。嵌入到页面中。
然而,通过PHP DOMDocument解析后,<gcse:search>
被转换为<search
>破坏功能
<?php
$html = <<<EOD
<!DOCTYPE html>
<html>
<body>
<gcse:search enablehistory="false"></gcse:search>
</body>
</html>
EOD;
libxml_use_internal_errors(true);
$dom = new DOMDocument();
$dom->loadHTML($html);
echo $dom->saveHTML();
输出:
<!DOCTYPE html>
<html>
<body>
<search enablehistory="false"></search>
</body>
</html>
您可以在解析html之前用占位符替换名称空间,并在saveHtml()
调用之后将它们转换回来。
<?php
$html = <<<EOD
<!DOCTYPE html>
<html>
<body>
<gcse:search enablehistory="false"></gcse:search>
<gcse:test enablehistory="false"></gcse:test>
<mynamespace:testing enablehistory="false">test</mynamespace:testing>
</body>
</html>
EOD;
$htmlNamespaces = ['gcse:', 'mynamespace:'];
$namespaceReplacements = array_map(function($index){
return "ns__" . $index;
}, array_keys($htmlNamespaces));
$html = str_replace($htmlNamespaces, $namespaceReplacements, $html);
libxml_use_internal_errors(true);
$dom = new DOMDocument();
$dom->loadHTML($html);
$rawHtml = $dom->saveHTML();
$formattedHtml = str_replace($namespaceReplacements, $htmlNamespaces, $rawHtml);
echo $formattedHtml;
结果:
<!DOCTYPE html>
<html>
<body>
<gcse:search enablehistory="false"></gcse:search>
<gcse:test enablehistory="false"></gcse:test>
<mynamespace:testing enablehistory="false">test</mynamespace:testing>
</body>
</html>
我发现的唯一解决方案是用___
替换:
,然后在saveHTML()
之后重新替换。
$html = preg_replace('/<(/?)([a-z]+):/', '<$1$2___', $html);
$doc->loadHTML($html);
// do stuff
$html = preg_replace('/<(/?)([a-z]+)___/', '<$1$2:', $doc->saveHtml());