使用 DOMDocument->saveHTML() 将实际 Unicode 字符自动转换为数值

Posted

技术标签:

【中文标题】使用 DOMDocument->saveHTML() 将实际 Unicode 字符自动转换为数值【英文标题】:The Actual Unicode Characters automatically converted to Numeric values using DOMDocument->saveHTML() 【发布时间】:2013-04-05 16:57:10 【问题描述】:

我正在使用下面的函数来获取html字符串的内部html

function DOMinnerHTML($element) 
 
    $innerHTML = ""; 
    $children = $element->childNodes; 
    foreach ($children as $child) 
     
        $tmp_dom = new DOMDocument('1.0', 'UTF-8');
        $tmp_dom->appendChild($tmp_dom->importNode($child, true)); 
        $innerHTML .= trim($tmp_dom->saveHTML()); 
    

    return $innerHTML; 
 

我的 html 字符串也包含 unicode 字符。这是html字符串的示例

$html = '<div>Thats True. Yes it is well defined آپ مجھے تم کہہ کر پکاریں</div>';

当我使用上述功能时

$output = DOMinnerHTML($html);

输出如下

$output = '<div>Thats True. Yes it is well defined 
&#1705;&#1746;&#1748;&#1587;&#1604;&#1591;&#1575</div>';

转换为数值的实际 unicode 字符。

我已经调试了代码,发现在DOMinnerHTML函数下面一行之前

$innerHTML .= trim($tmp_dom->saveHTML()); 

如果我回声

echo $tmp_dom->textContent;

它显示实际的 unicode 字符,但在保存到 $innerHTML 后,它会输出数字符号。 为什么这样做。

注意:请不要建议我使用 html_entity_decode 之类的函数将数字符号转换为真正的 unicode 字符,因为我的 html 字符串中还有用户格式化的数据,我不想转换。

注意:我也试过把

<meta http-equiv="content-type" content="text/html; charset=utf-8">

在我的 html 字符串之前,但没有区别。

【问题讨论】:

相关:***.com/questions/6573258/… 呃,有问题吗?数字字符引用应该仍然可以正常工作。好的,它们只是占用了更多的字节...... 【参考方案1】:

我遇到了类似的问题。看了上面的评论,经过进一步的调查,我找到了一个非常简单的解决方案。

你所要做的就是使用html_entity_decode()来转换saveHTML()的输出,如下:

// Create a new dom document
$dom = new DOMDocument();


// .... Do some stuff, adding nodes, ...etc.


// the html_entity_decode function will solve the unicode issue you described
$result = html_entity_decode($dom->saveHTML();

// echo your output
echo $result;

这将确保正确显示 unicode 字符

【讨论】:

【参考方案2】:

问得好,您做得很好,将问题缩小到导致事情变得混乱的一行代码!这让我能够弄清楚出了什么问题。

问题在于DOMDocument's saveHTML() function。它正在做它应该做的事情,但它的设计不是你想要的。

saveHTML() 将文档转换为“使用 HTML 格式”的字符串 - 这意味着它会为您进行 HTML 实体编码!可悲的是,这不是你想要的。 php 文档中的注释还表明 DOMDocument 不能很好地处理 utf-8 并且不能很好地处理片段(因为它会自动添加 html、doctype 等)。

只需使用另一个类即可查看此评论以获取建议的解决方案:alternative to DOMDocument

在看到许多关于某些 DOMDocument 缺点的投诉后, 例如编码处理不当和总是保存 HTML 片段 使用 、 和 DOCTYPE,我认为更好的解决方案是 需要。

所以这里是:SmartDOMDocument。你可以在 http://beerpla.net/projects/smartdomdocument/

目前主要亮点有:

SmartDOMDocument 继承自 DOMDocument,因此非常易于使用 - 只需声明一个 SmartDOMDocument 类型的对象而不是 DOMDocument 并在所有现有的基础上享受新的行为 功能(参见下面的示例)。

saveHTMLExact() - DOMDocument 有一个设计非常糟糕的“功能”,如果您正在加载的 HTML 代码不包含 和标签,它会自动添加它们(是的,没有 标志来关闭此行为)。因此,当您调用 $doc->saveHTML(),你新保存的内容现在有和 DOCTYPE 在里面。尝试使用代码片段时不是很方便 (XML 也有类似的问题)。 SmartDOMDocument 包含一个新功能 调用 saveHTMLExact() 完全符合您的要求 - 它 保存 HTML 而不会像 DOMDocument 那样添加额外的垃圾。

编码修复 - 众所周知,DOMDocument 不能正确处理编码(至少是 UTF-8)并且输出会出现乱码。 SmartDOMDocument 尝试 通过增强 loadHTML() 来解决这个问题 正确编码。这种行为对您来说是透明的 - 只需使用 像往常一样加载HTML()。

【讨论】:

感谢您的详细回答。其实你已经深入了解了我的问题。但是这个答案中给出的课程,我下载并使用了它,但存在同样的问题。即使您尝试这个 SmartDOMDocument 类的 testHTML() 函数,它也会详细说明它本身并不显示实际的 unicode 字符,而是显示数字等值 html 代码。那是我的实际问题。等待解决方案。【参考方案3】:

mb_convert_encoding($html,'HTML-ENTITIES','UTF-8');

这对我有用

【讨论】:

以上是关于使用 DOMDocument->saveHTML() 将实际 Unicode 字符自动转换为数值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 PHP DOMDocument 链接类似元素?

使用 DOMDocument PHP 获取 Xpath 父节点?

如何使用 DOMDocument 替换节点的文本

使用 DOMDocument->saveHTML() 将实际 Unicode 字符自动转换为数值

使用 DOMDocument 生成站点地图:输出中缺少 AttributeNode

DOMDocument & XPath - 每个节点的 HTML 标签