[PHP] DOMDocumentでloadHTMLして文字化けする時の対処方法

状況

下記のコードを実行した際にマルチバイト文字が文字化けする。

// h2 要素のみ取り出し
$content = '<h2>見出し</h2><p>文章</p>';
$headings = [];
$dom = new DOMDocument();
$dom->loadHTML($content);
$nodes = $dom->getElementsByTagName('h2');

foreach ($nodes as $node) {
  $headings[] = $node->textContent;
}

見出し -> 見出し となってしまう。

方法

// h2 要素のみ取り出し
$content = '<h2>見出し</h2><p>文章</p>';
$headings = [];
$dom = new DOMDocument();
$dom->loadHTML(mb_convert_encoding($content, 'HTML-ENTITIES', 'UTF-8'));
$nodes = $dom->getElementsByTagName('h2');

foreach ($nodes as $node) {
  $headings[] = $node->textContent;
}

DOMDocument::loadHTMLは、文字列をISO-8859-1として扱うため UTF-8 文字が化けてしまっている。
なので、mb_convert_encodingで UTF-8 へ変換して$dom->loadHTMLへ文字列を渡すようにする。

下記のようなDOCTYPEの宣言が含まれている文字列だと UTF-8 として解釈してくれる。

$dom->loadHTML('<?xml encoding="utf-8" ?>' . $content);