記事一覧

PHPでSimpleXMLに &(アンパサンド) を渡すとエラーになる件




目次



本記事を書いた時点でのPHPの最新バージョンは、PHP5.6です。

SimpleXMLの意外な盲点

ハロー、みなさん。エジソンです。

PHPでXMLを扱うには、SimpleXMLの利用が便利です。

PHP - SimpleXML
SimpleXML拡張モジュールは、 XMLをオブジェクトにとても簡単かつ容易に変換するための機能を提供します。変換後のオブジェクトでは、 通常のプロパティセレクタや配列反復子を用いて処理を行うことが可能です。

とあるプロジェクトで、SimpleXMLを利用していた際に、ある特定の条件下で発生する問題がありました。

その問題というのが、子要素を追加する際に、文字列に &(アンパサンド) を含めるとエラーが発生するというものです。

当初は、このようなエラーが発生するというのは、SimpleXML自身のバグかと思ったのですが、世界中で報告されている有名な問題のようです。バグレポートも詳しく読んでいないので、バグなのか仕様なのか正直分かっていません。

とは言え、待っていても問題が解決するわけではないので、 &(アンパサンド) をエスケープした上で、SimpleXMLを利用するのがベストでしょう。

SimpleXMLのaddChildでエラーを引き起こしてみる

とりあえず、本当にエラーが発生するのかを確認してみましょう。

サンプルコード
<?php

$string = <<<XML
<?xml version='1.0'?> 
<document> 
    <cmd>login</cmd> 
    <login>Richard</login> 
</document> 
XML;
                                                                        
$xml = simplexml_load_string($string);

// 子要素を追加
$child = $xml->addChild('child', 'Child of element');
// 子要素に属性を追加
$child->addAttribute('childAttr', 'Attribute of child element');

// NG : (コメントを外すとエラーになります!)子要素を追加
//$errorChild = $xml->addChild('errorChild', '&Child of element');
// OK : (&をエスケープしているので正常に通過する)子要素を追加
$errorChild = $xml->addChild('errorChild', str_replace('&', '&amp;', '&Child of element'));

// xmlを整形して出力する
$dom = new DOMDocument("1.0");
$dom->preserveWhiteSpace = false;
$dom->formatOutput = true;
$dom->loadXML($xml->asXML());
$dom->formatOutput = true;
echo $dom->saveXML();

?>

結果(正常時)
<?xml version="1.0"?>
<document>
  <cmd>login</cmd>
  <login>Richard</login>
  <child childAttr="Attribute of child element">Child of element</child>
  <errorChild>&Child of element
</document>

結果(異常時、コメントアウトをはずした場合)
PHP Warning:  SimpleXMLElement::addChild(): unterminated entity reference Child of element in /workspace/Main.php on line 20

上述したコードの、18行目のコメントアウトを外すとエラーが発生することがわかります。一方で、&(アンパサンド)に対して、str_replace関数を用いて文字列変換を実施した場合には正常に動作することがわかりました。

まとめ

SimpleXMLのSimpleXMLElementクラスの、addChildの第二引数に与える文字列には、&(アンパサンド)を含めるとエラーになるので注意が必要です。

事前に、str_replace関数などで、&(アンパサンド)を&amp;に変換すると良いでしょう。


関連記事

このエントリーをはてなブックマークに追加

コメント

コメントの投稿

非公開コメント

プロフィール

EZOLABブログへようこそ。
EZOLABは、札幌のソフトウェア会社です。

http://ezolab.co.jp