考虑到使用包含表情符号字符的样式表构建的
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: "⚡️"; }</style>
</head><body><span></span></body></html>
请注意表情符号“⚡️”如何编码为样式表内的 HTML 实体
⚡️
。它被视为文字字符串,因为应使用 CSS 转义 \26A1
。
我尝试设置
$dom->substituteEntities = false
但没有任何效果。
相同的 HTML 实体转换也发生在
<script>
元素内部,这会在浏览器中导致类似的问题。
通过在线 PHP shell 进行测试:https://3v4l.org/jMfDd
您应该在 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