雑多なブログ

音楽や語学、プログラム関連の話題について書いています

PHP: DOMXPathでは、nodeValueに & を含む文字列を代入できない。

DOMXPathでnodeValueに&を含む文字列を代入しようとしたら警告が出た。

PHP Warning:  main(): unterminated entity reference         

実行結果を見てみると、代入はできておらず、代入する前の元の文字列も抜け落ちていた。

string(35) "<div>
    <p id="text"></p>
</div>
"

検証に使用したソースはこちら

<?php
$html=<<<EOS
<div>
    <p id="text">default</p>
</div>
EOS;

$dom = new DOMDocument;
@$dom->loadHTML($html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);

$xpath = new DOMXPath($dom);
$node = $xpath->query('//*[@id="text"]');
$node[0]->nodeValue = 'Hello&';

var_dump($dom->saveHTML());

対策

&を含むテキストをnodeValueに代入する時は、htmlspecialchars()を使ってエスケープするか、直接 & をhtml文字参照の形式 &amp; に変換するか対応が必要だった。

変更前

$node[0]->nodeValue = 'Hello&';

変更例1

$node[0]->nodeValue = htmlspecialchars('Hello&');

変更例2

$node[0]->nodeValue = str_replace('&', '&amp;', 'Hello&');