为什么 DOMDocument::saveHTML() 的行为在将 UTF-8 编码为样式和脚本元素中的实体时有所不同?

问题描述 投票:0回答:1

考虑到使用包含表情符号字符的样式表构建的

DOMDocument
,我在将 DOM 序列化回 HTML 时发现了一些奇怪的行为。

$html = <<< HTML
<!DOCTYPE html>
<html>
<head>
  <meta charset=utf-8>
  <style>span::before{ content: \"⚡️\"; }</style>
</head>
<body>
  <span></span>
</body>
</html>
HTML;
$dom = new DOMDocument();
$dom->loadHTML($html);

echo $dom->saveHTML($dom->documentElement);
echo $dom->saveHTML();

$dom->saveHTML($dom->documentElement)
的结果是(根据需要):

<html><head><meta charset="utf-8">
<style>span::before{ content: "⚡️"; }</style>
</head><body><span></span></body></html>

但是

$dom->saveHTML()
返回(错误地):

<html><head><meta charset="utf-8">
<style>span::before{ content: "&#9889;&#65039;"; }</style>
</head><body><span></span></body></html>

请注意表情符号“⚡️”如何编码为样式表内的 HTML 实体

&#9889;&#65039;
。它被视为文字字符串,因为应使用 CSS 转义
\26A1

我尝试设置

$dom->substituteEntities = false
但没有任何效果。

相同的 HTML 实体转换也发生在

<script>
元素内部,这会在浏览器中导致类似的问题。

通过在线 PHP shell 进行测试:https://3v4l.org/jMfDd

php dom domdocument html-entities
1个回答
1
投票

您应该在 DOMDocument 上加载带有表情符号的 HTML 之前转换编码:

$dom->loadHTML(mb_convert_encoding($htmlCode, 'HTML-ENTITIES', 'UTF-8'));

编辑:正如帖子所有者提到的,mb_convert_enconding 在未来的 PHP 版本中已被弃用(目前在 8.2.5 上进行了测试并且工作正常)。对于更高版本的 PHP,请查看 https://php.watch/versions/8.2/mbstring-qprint-base64-uuencode-html-entities-deprecated#html

© www.soinside.com 2019 - 2024. All rights reserved.