先週「SimpleXMLモジュールを使ってAPIから取得したXMLを簡単に処理する」という記事を書きましたが、
今週もそれに関連する内容を書いてみます。
XMLをいかにすばやく楽に配列に取得するかということで、
前回はSimpleXMLモジュールを使い、
その後、get_object_varsで配列型にするという手順で行いました。
ただしこの手順での問題は、get_object_varsは再帰的に処理できないというところでした。
ですので、最後は地道にarrayの型キャストを使い、配列に置換していました。
今回はもっと簡単に再帰的にXMLを処理する方法はないのかということで、
こんな方法をご紹介します。
前回の最後にちょこっと書いた、
SPL(Standard PHP Library)のArrayObjectを使うという方法ではありません。
ZendFramework使ったやり方ですが、手順の差はあれどPHP単体でも実行できます。
方法の概略をお伝えすると、
XMLを取得して、JSON形式に変換し、最後にそれを配列へデコードするという方法です。
では実際に、やってみましょう。
前回同様、XMLを取得します。
$word = '難波'; // 検索する駅を難波にしてみる $word = mb_convert_encoding($word, 'UTF-8', 'auto'); // APIを使用するURLを生成 $url = 'http://map.yahooapis.jp/LocalSearchService/V1/LocalSearch?' . 'appid=*****************' . '&p=' . $word . '&category=station' // 駅名のみ検索するときのパラメータ . '&n=100' . '&datum=wgs'; //結果を取得 $contents = file_get_contents($url); var_dump($contents);
結果は前回同様同じです。
<LocalSearchResult xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="urn:yahoo:jp:maps http://api.map.yahoo.co.jp/LocalSearchService/V1/LocalSearch/LocalSearchResponse.xsd"> <Count>3</Count> <ViewCount>3</ViewCount> <Query>難波</Query> <Item> <Category>Station</Category> <Title>難波駅</Title> <Address>大阪府大阪市浪速区難波中</Address> <AddressLevel>0</AddressLevel> <DatumTky97> <Lat>34.66005533</Lat> <Lon>135.50483289</Lon> </DatumTky97> <DatumWgs84> <Lat>34.663312792164</Lat> <Lon>135.50202380723</Lon> </DatumWgs84> <Url /> </Item> <Item> <Category>Station</Category> <Title>近鉄難波駅</Title> <Address>大阪府大阪市中央区難波</Address> <AddressLevel>0</AddressLevel> <DatumTky97> <Lat>34.66394422</Lat> <Lon>135.50194444</Lon> </DatumTky97> <DatumWgs84> <Lat>34.667201194399</Lat> <Lon>135.49913552432</Lon> </DatumWgs84> <Url /> </Item> <Item> <Category>Station</Category> <Title>JR難波駅</Title> <Address>大阪府大阪市浪速区湊町</Address> <AddressLevel>0</AddressLevel> <DatumTky97> <Lat>34.66341578</Lat> <Lon>135.49852756</Lon> </DatumTky97> <DatumWgs84> <Lat>34.66667276344</Lat> <Lon>135.49571895486</Lon> </DatumWgs84> <Url /> </Item> </LocalSearchResult><!-- fe01.map.bbt.yahoo.co.jp uncompressed Wed Dec 17 11:18:08 JST 2008 -->
前回はこの後、simplexml_load_stringを使ってまずobject型に直していましたが、
今回はここでこのXMLをJSONに変換します。
Zend_Jsonを使います。手順は増えますが、
ZendFrameworkを使っていない人でもこの操作はできます。調べてみてください。
参考サイト:Do You PHP?
require_once 'Zend/Json.php'; //Zend_Jsonを呼び出します $jsonContents = Zend_Json::fromXml($contents, true); var_dump($jsonContents);
ここでZend_Json::fromXmlを使います。
中身はこのようになっています。
string(946) "{"LocalSearchResult":{"Count":"3","ViewCount":"3","Query":"\u96e3\u6ce2","Item": [{"Category":"Station","Title":"\u96e3\u6ce2\u99c5","Address":"\u5927\u962a\u5e9c\u5927\u962a\u5e02\u6d6a\u901f\u533a\u96e3\u6ce2\u4e2d", "AddressLevel":"0","DatumTky97":{"Lat":"34.66005533","Lon":"135.50483289"},"DatumWgs84":{"Lat":"34.663312792164","Lon":"135.50202380723"}, "Url":""},{"Category":"Station","Title":"\u8fd1\u9244\u96e3\u6ce2\u99c5","Address":"\u5927\u962a\u5e9c\u5927\u962a\u5e02\u4e2d\u592e\u533a\u96e3\u6ce2", "AddressLevel":"0","DatumTky97":{"Lat":"34.66394422","Lon":"135.50194444"},"DatumWgs84":{"Lat":"34.667201194399","Lon":"135.49913552432"},"Url":""}, {"Category":"Station","Title":"\uff2a\uff32\u96e3\u6ce2\u99c5","Address":"\u5927\u962a\u5e9c\u5927\u962a\u5e02\u6d6a\u901f\u533a\u6e4a\u753a","AddressLevel": "0","DatumTky97":{"Lat":"34.66341578","Lon":"135.49852756"},"DatumWgs84":{"Lat":"34.66667276344","Lon":"135.49571895486"},"Url":""}]}}"
上手くJSONに変換できたようです。
ただこのままではすごく扱いにくいので、
これをPHPで簡単に使えるようにデコードしてあげます。
$array = Zend_Json::decode($jsonContents); var_dump($array);
使用するメソッドはZend_Json::decodeです。
するとこんな感じに変換できます。
array(1) { ["LocalSearchResult"]=> array(4) { ["Count"]=> string(1) "3" ["ViewCount"]=> string(1) "3" ["Query"]=> string(6) "難波" ["Item"]=> array(3) { [0]=> array(7) { ["Category"]=> string(7) "Station" ["Title"]=> string(9) "難波駅" ["Address"]=> string(36) "大阪府大阪市浪速区難波中" ["AddressLevel"]=> string(1) "0" ["DatumTky97"]=> array(2) { ["Lat"]=> string(11) "34.66005533" ["Lon"]=> string(12) "135.50483289" } ["DatumWgs84"]=> array(2) { ["Lat"]=> string(15) "34.663312792164" ["Lon"]=> string(15) "135.50202380723" } ["Url"]=> string(0) "" } [1]=> array(7) { ["Category"]=> string(7) "Station" ["Title"]=> string(15) "近鉄難波駅" ["Address"]=> string(33) "大阪府大阪市中央区難波" ["AddressLevel"]=> string(1) "0" ["DatumTky97"]=> array(2) { ["Lat"]=> string(11) "34.66394422" ["Lon"]=> string(12) "135.50194444" } ["DatumWgs84"]=> array(2) { ["Lat"]=> string(15) "34.667201194399" ["Lon"]=> string(15) "135.49913552432" } ["Url"]=> string(0) "" } [2]=> array(7) { ["Category"]=> string(7) "Station" ["Title"]=> string(15) "JR難波駅" ["Address"]=> string(33) "大阪府大阪市浪速区湊町" ["AddressLevel"]=> string(1) "0" ["DatumTky97"]=> array(2) { ["Lat"]=> string(11) "34.66341578" ["Lon"]=> string(12) "135.49852756" } ["DatumWgs84"]=> array(2) { ["Lat"]=> string(14) "34.66667276344" ["Lon"]=> string(15) "135.49571895486" } ["Url"]=> string(0) "" } } } }
見事、短い手順で再帰的に配列に直すことに成功しました。
これでAPIで大量のデータを取ってきても、
ほんの数秒で処理することが出来ます。
前回のSimpleXMLモジュールを使うよりこっちの方が簡単でいいですね。