PHP DOMDocument loadHTML 未正确编码 UTF-8

2022-08-30 06:14:24

我试图使用DOMDocument解析一些HTML,但是当我这样做时,我突然失去了编码(至少在我看来是这样)。

$profile = "<div><p>various japanese characters</p></div>";
$dom = new DOMDocument();
$dom->loadHTML($profile); 

$divs = $dom->getElementsByTagName('div');

foreach ($divs as $div) {
    echo $dom->saveHTML($div);
}

这段代码的结果是,我得到了一堆不是日语的字符。但是,如果我这样做:

echo $profile;

它正确显示。我尝试过 saveHTML 和 saveXML,但两者都无法正确显示。我使用的是 PHP 5.3。

我看到的:

ã¤ãªãã¤å·ã·ã«ã´ã«ã¦ãã¢ã¤ã«ã©ã³ãç³»ã®å®¶åº­ã«ã9人åå¼ã®5çªç®ã¨ãã¦çã¾ãããå½¼ãå«ãã¦4人ã俳åªã«ãªã£ããç¶è¦ªã¯æ¨æã®ã»ã¼ã«ã¹ãã³ã§ãæ¯è¦ªã¯éµä¾¿å±ã®å®¢å®¤ä¿ã ã£ããé«æ ¡æ代ã¯ã­ã£ãã£ã®ã¢ã«ãã¤ãã«å¤ãã¿ãæè²è³éãåããªããã«ããªãã¯ç³»ã®é«æ ¡ã¸é²å­¦ã

应该显示的内容:

イリノイ州シカゴにて、アイルランド系の家庭に、9人兄弟の5番目として生まれる。彼を含めて4人が俳優になった。父親は木材のセールスマンで、母親は郵便局の客室係だった。高校時代はキャディのアルバイトに勤しみ、教育資金を受けながらカトリック系の高校へ進学

编辑:我已经将代码简化为五行,因此您可以自己测试它。

$profile = "<div lang=ja><p>イリノイ州シカゴにて、アイルランド系の家庭に、</p></div>";
$dom = new DOMDocument();
$dom->loadHTML($profile);
echo $dom->saveHTML();
echo $profile;

下面是返回的 html:

<div lang="ja"><p>イリノイ州シカゴã«ã¦ã€ã‚¢ã‚¤ãƒ«ãƒ©ãƒ³ãƒ‰ç³»ã®å®¶åº­ã«ã€</p></div>
<div lang="ja"><p>イリノイ州シカゴにて、アイルランド系の家庭に、</p></div>

答案 1

DOMDocument::loadHTML将把你的字符串视为 ISO-8859-1(HTTP/1.1 默认字符集),除非你另有说明。这会导致 UTF-8 字符串被错误地解释。

如果字符串不包含 XML 编码声明,则可以在前面附加一个,以使该字符串被视为 UTF-8:

$profile = '<p>イリノイ州シカゴにて、アイルランド系の家庭に、9</p>';
$dom = new DOMDocument();
$dom->loadHTML('<?xml encoding="utf-8" ?>' . $profile);
echo $dom->saveHTML();

如果您无法知道字符串是否已经包含这样的声明,那么SmartDOMDocument中有一个解决方法,应该可以帮助您:

$profile = '<p>イリノイ州シカゴにて、アイルランド系の家庭に、9</p>';
$dom = new DOMDocument();
$dom->loadHTML(mb_convert_encoding($profile, 'HTML-ENTITIES', 'UTF-8'));
echo $dom->saveHTML();

这不是一个很好的解决方法,但由于并非所有字符都可以在ISO-8859-1中表示(如这些武士刀),因此它是最安全的替代方案。


答案 2

问题在于 和 ,它们都不能在 Unix 中正常工作。它们在Unix中使用时不会正确保存UTF-8字符,但它们在Windows中工作。saveHTML()saveXML()

解决方法非常简单:

如果您尝试使用默认值,您将收到您描述的错误

$str = $dom->saveHTML(); // saves incorrectly

您所要做的就是保存如下:

$str = $dom->saveHTML($dom->documentElement); // saves correctly

这行代码将正确保存 UTF-8 字符。如果您使用的是 ,请使用相同的解决方法。saveXML()


更新

正如“Jack M”在下面的评论部分中所建议的那样,并由“Pamela”和“Marco Aurélio Deleu”验证,以下变体可能适用于您的情况:

$str = utf8_decode($dom->saveHTML($dom->documentElement));

注意

  1. 在没有参数的情况下使用时,英文字符不会导致任何问题(因为英文字符在 UTF-8 中保存为单字节字符)saveHTML()

  2. 当您有多字节字符(例如中文,俄语,阿拉伯语,希伯来语,...等)

我建议阅读这篇文章:http://coding.smashingmagazine.com/2012/06/06/all-about-unicode-utf8-character-sets/。您将了解 UTF-8 的工作原理以及为什么会出现此问题。这将花费您大约30分钟,但这段时间花得很好。


推荐