PHPでXML解析

いろいろと調べてみると、面白いもので、知らないことがいっぱい。
PHPでXML解析をするときは、基本的に、XML_Serializerを使う必要があると思ってました。XML_Serializerは、PEARにあるのですが、まだ、PHPの標準関数には、XMLを扱うものが無いのではないかと思って、そればかり使ってました。
数KB程度のXMLだと問題ないのですが、巨大なXMLファイルとなると、少々厄介です。XML_SerializerはDOM形式ですべてメモリに展開してしまいます。
今回、仕事上で、巨大なファイルを扱うことになり、なにかいい方法が無いか調べてましたら、ありました。PHPのバージョンからすると1年前にはすでにあったっぽいですけどね。
最近のバージョンだと、./configureで指定しなくとも、標準で入っているようです。
XMLReader関数
これはXMLノードを順に呼び出しながらデータ取得をします。
ファイルをオープンして、一行ずつ処理していくような感じです。
webのPHPマニュアルページには、『5.1.0からデフォルトで組み込まれ・・・』とありますが、関数リファレンスを見ると『(PHP 5 >= 5.1.2)』となっているので注意してください。
で、いざ、使おうと思ったら、サンプルが無い。
試行錯誤中に、もうひとつ発見したのが、PEARのXML_Serializerの代わりとなるsimplexml_import_domというものがありました。simplexmlは、PHP5が出たときにあったのは知ってましたが、バグが多いのか、メソッドが存在してなかったり、大変でした。
試行錯誤して、できたのが次のプログラム。
(ブログ掲載用に書き換えてます)

// テスト用にローカルにXMLを配置しているので読み込みしてるけど、巨大XMLファイルの場合は、ストリームで読み込むことになる。
$buf = file_get_contents(‘hogehoge.xml’);
// インスタンス生成
$reader = new XMLReader();
// XML読み込み。ストリームからは、openメソッドを使う。$reader->open(“URI”)
$reader->xml($buf);
// 最初のread()でrootドキュメント参照
$reader->read();
// 子のノードへ移動
$reader->read();
// localNameプロパティでタグ名を参照
echo $reader->localName;
// ぉかlNameで確認したタグ以下のノード全体をDOMで取得
$node = $reader->expand();
// domドキュメントを作成
$dom = new DOMDocument(“1.0″,”UTF-8”);
// データ読み込み
$n = $dom->importNode($node,true);
// 適用
$dom->appendChild($n);
// dom構造をPHPアクセス可能な変数形式に変更
$s = simplexml_import_dom($n);

XMLファイルをタグ以下読み込みとできるので、分割して順に読みながら処理していくことができ、サーバーがパンクすることを防ぐことができました。

コメントを残す

%d人のブロガーが「いいね」をつけました。