使用 PHP DOMDocument 时 <gcse:search> 转换为 <search>

<gcse:search> converted to <search> when using PHP DOMDocument

我有以下 HTML 代码和自定义标签 <gcse:search>。它来自“自定义 Google 搜索引擎”以嵌入页面。

然而,在通过 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]+)\:/', '<___', $html);
$doc->loadHTML($html);
// do stuff
$html = preg_replace('/<(\/?)([a-z]+)___/', '<:', $doc->saveHtml());