2007-04-26 01:46
PHP4でAWSのXMLをパースする
なんだかタイトルが暗号のようになったが、「いもづる式」を作る過程で気づいたことなどをメモしておく。
Amazon Web Serviceを使ってサービスを作るといっても、RESTで投げて結果を受け取って表示するだけである。クエリーの組み立てはマニュアルを熟読すれば良いとして、私のような素人プログラマが苦労するのは、やはりXMLのパース部分だろう。PHP5が使えればSimpleXML関数を使うのが便利らしいが、使っているレンタルサーバーがPHP4なので駄目だった。いくつか候補はあったが、最終的に使ったのはPEARのXML_Serializerである。ネットで検索しても、これを使っているケースが多いので、サンプルコードも見つかるだろう。実際にはこの中のUnserializer.phpを使う。
こんな感じで、$dataの中に多次元配列の形で入ってくれるので、後は必要な部分を取り出せばいい。どのクエリーを使うかにもよるが、例えば一冊目のタイトルなら
$data['Items']['Item'][0]['ItemAttributes']['Title']
のような感じになる。だいたい構造が分からなくなるので、$dataをprint_rしてチェックするのが吉。
ここからが本題。実際にやってみて困ったのが、XMLで得られる件数が1か2以上かが分からないケースで、Unserializerを初期設定のまま使うと配列の形式が異なってしまうことだ。例えばキーワード検索した場合の結果は1件かもしれないが、その時は上記のタイトルが
$data['Items']['Item']['ItemAttributes']['Title']
となってしまう。これではいちいち返り値(の特定部分)が配列かどうかをis_arrayで調べないといけなくなり、ifだらけになるのだ。
ネットで検索しても見つけられなかったんだけど、冷静にマニュアルを見たら、ちゃんとオプションがあった。
このforceEnumに該当アイテムを指定してやると、1件しかなくても配列にしてくれる。つまり上記タイトルの例では[0]が入る。これでforeachで回せば処理が1種類で済む。めでたしめでたし(上記は長くなるので3つしか入れていないが、実際には倍以上設定することになると思う)。
あと気をつけないといけないのは、データが入っているとは限らないアイテムがあるということ。画像が無いケースがあるのはAmazonを使っていれば分かると思うが、大きなサイズだけ無いとかいう場合もある。著者が空欄だとか、古書はBinding(単行本等の表記)が無いとか。特に説明されているドキュメントはなさそうなので、ある程度目で見るしかないような気がする。
Amazon Web Serviceを使ってサービスを作るといっても、RESTで投げて結果を受け取って表示するだけである。クエリーの組み立てはマニュアルを熟読すれば良いとして、私のような素人プログラマが苦労するのは、やはりXMLのパース部分だろう。PHP5が使えればSimpleXML関数を使うのが便利らしいが、使っているレンタルサーバーがPHP4なので駄目だった。いくつか候補はあったが、最終的に使ったのはPEARのXML_Serializerである。ネットで検索しても、これを使っているケースが多いので、サンプルコードも見つかるだろう。実際にはこの中のUnserializer.phpを使う。
$Unserializer =&new XML_Unserializer($options);
$Unserializer->unserialize($xml);
$data = $Unserializer->getUnserializedData();
$Unserializer->unserialize($xml);
$data = $Unserializer->getUnserializedData();
こんな感じで、$dataの中に多次元配列の形で入ってくれるので、後は必要な部分を取り出せばいい。どのクエリーを使うかにもよるが、例えば一冊目のタイトルなら
$data['Items']['Item'][0]['ItemAttributes']['Title']
のような感じになる。だいたい構造が分からなくなるので、$dataをprint_rしてチェックするのが吉。
ここからが本題。実際にやってみて困ったのが、XMLで得られる件数が1か2以上かが分からないケースで、Unserializerを初期設定のまま使うと配列の形式が異なってしまうことだ。例えばキーワード検索した場合の結果は1件かもしれないが、その時は上記のタイトルが
$data['Items']['Item']['ItemAttributes']['Title']
となってしまう。これではいちいち返り値(の特定部分)が配列かどうかをis_arrayで調べないといけなくなり、ifだらけになるのだ。
ネットで検索しても見つけられなかったんだけど、冷静にマニュアルを見たら、ちゃんとオプションがあった。
$options= array(
'parseAttributes' => TRUE,
'forceEnum' => array('Item','Review','Error')
);
'parseAttributes' => TRUE,
'forceEnum' => array('Item','Review','Error')
);
このforceEnumに該当アイテムを指定してやると、1件しかなくても配列にしてくれる。つまり上記タイトルの例では[0]が入る。これでforeachで回せば処理が1種類で済む。めでたしめでたし(上記は長くなるので3つしか入れていないが、実際には倍以上設定することになると思う)。
あと気をつけないといけないのは、データが入っているとは限らないアイテムがあるということ。画像が無いケースがあるのはAmazonを使っていれば分かると思うが、大きなサイズだけ無いとかいう場合もある。著者が空欄だとか、古書はBinding(単行本等の表記)が無いとか。特に説明されているドキュメントはなさそうなので、ある程度目で見るしかないような気がする。
