XMLをJSONを使って簡単に配列に変換する方法

By fukumoto - 08/12/17 - このエントリをはてなブックマークに追加このエントリをYahoo!ブックマークに追加このエントリをdel.icio.usに追加このエントリをFC2ブックマークに追加

先週「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型に直していましたが、
今回はここでこのXMLJSONに変換します。
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モジュールを使うよりこっちの方が簡単でいいですね。