2011年2月21日月曜日

PHP Zend_Config_XMLをsimplexml_load_stringに書き換える

XMLのParseにZend_Config_XMLを使ってみたがParse用ではなくConfigファイルを読むためのものっぽいので、simplexml_load_stringに書き換えることにした。

simplexml_load_stringはSimpleXMLElementを返す。サンプルコードは前回のようにこんな感じ。
$ cat sample_simplexml_load_string.php 
<?php

$string = <<< "END"
<?xml version="1.0" ?>
<ResultSets>
  <Result>
    <field>
      <id>1</id>
      <title>hoge</title>
    </field>
    <field>
      <id>2</id>
      <title>fuga</title>
    </field>
  </Result>
</ResultSets>
END;
$sxe = simplexml_load_string($string);
var_dump($sxe);
で、結果としてはこんな構造のものが返ってくる。
$ cat sample_simplexml_load_string.php
object(SimpleXMLElement)#1 (1) {
  ["Result"]=>
  object(SimpleXMLElement)#2 (1) {
    ["field"]=>
    array(2) {
      [0]=>
      object(SimpleXMLElement)#3 (2) {
        ["id"]=>
        string(1) "1"
        ["title"]=>
        string(4) "hoge"
      }
      [1]=>
      object(SimpleXMLElement)#4 (2) {
        ["id"]=>
        string(1) "2"
        ["title"]=>
        string(4) "fuga"
      }
    }
  }
}
fieldが2つ以上の場合だと、上記のようにfieldがarray。
fieldが1つだけの場合だと、下記のようにfieldがobject。

object(SimpleXMLElement)#1 (1) {
  ["Result"]=>
  object(SimpleXMLElement)#2 (1) {
    ["field"]=>
    object(SimpleXMLElement)#3 (2) {
      ["id"]=>
      string(1) "1"
      ["title"]=>
      string(4) "hoge"
    }
  }
}
これはZend_Config_XMLと同様にfieldが1つの場合を判断して処理をいれないといけないように思われるのだが、下記のコードで良きに計らって処理される。SimpleXMLElementクラスあたりをちゃんと調べれば、なぜ上手く行くかはわかるとは思うので、時間があれば調べる。
foreach($sxe->Result->field as $field) {
    /*処理*/
}

あと、先日見た通りZend_Config_XMLは内部でsimplexml_load_string使ってたわけで、どっちがパフォーマンスがいいかと言われればsimplexml_load_stringをそのまま使う方に軍配が上がるだろう。実際に、先のサンプルを出力部分コメントアウトして10000回それぞれ実行してみた時間は下記の通り。予想通りにsimplexml_load_stringの方が速い。
$ time for i in `seq 10000`; do php sample_zend_config_xml.php ; done;

real 2m49.519s
user 1m45.908s
sys 0m57.570s

$ time for i in `seq 10000`; do php sample_simplexml_load_string.php ; done;

real 2m39.058s
user 1m36.316s
sys 0m57.248s