サンプル・プログラム

解説:準備
0023: // GeoCodeクラス =============================================================
0024: class pahooGeoCode {
0025: var $items; //検索結果格納用
0026: var $error; //エラーフラグ
0027: var $hits; //検索ヒット件数
0028: var $webapi; //直前に呼び出したWebAPI URL
0029:

WebAPI「ジオどす II」では API キーが必要になる。これは http://geodosu.com/user/register から無料で入手することができる。この API キーの値は定数 APIKEY_GEODOS にあらかじめ設定しておく。
また、今回は使用しないが、Yahoo! JAPAN Web サービスを利用する場合は、アプリケーション ID を https://account.edit.yahoo.co.jp/registration から無償取得し、定数 YAHOO_APPLICATION_ID に設定しておく。
解説:XMLパーシング
0107: * @param string $xml XMLファイル名
0108: * @return object DOMオブジェクト/NULL 失敗
0109: */
0110: function read_xml($xml) {
0111: if ($this->isphp5over()) return NULL;
0112: if (($fp = fopen($xml, 'r')) == FALSE) return NULL;
0113:
0114: //いったん変数に読み込む
0115: $str = fgets($fp);
0116: $str = preg_replace('/UTF-8/', 'utf-8', $str);
0117:
0118: while (! feof($fp)) {
0119: $str = $str . fgets($fp);
0120: }
0121: fclose($fp);
0122:
0123: //DOMを返す
0124: $dom = domxml_open_mem($str);
0125: if ($dom == NULL) {
0126: echo "\n>Error while parsing the document - " . $xml . "\n";
0127: exit(1);
0128: }
0129:
0130: return $dom;
0131: }
0132:
0133: /**
0134: * GoogleMaps API Geocoding(V3) のURLを取得する
0135: * @param string $query 検索キーワード(UTF-8)
0136: * @return string URL URL
0137: */
0138: function getURL_GeoCodeAPI_V3($query) {
0139: $key = $this->GOOGLE_API_KEY;
0140: return "https://maps.googleapis.com/maps/api/geocode/xml?key={$key}&language=ja®ion=JP&address=" . urlencode($query);
0141: }
0142:
0143: /**
0144: * Google Geocoding API(V3) を用いて住所・駅名の緯度・経度を求める
0145: * @param string $query 検索キーワード
0146: * @param array $items 情報を格納する配列
0147: * @return int ヒットした施設数
0148: */
0149: function getPointsV3_all($query, &$items) {
0150: $url = $this->getURL_GeoCodeAPI_V3($query); //リクエストURL
0151: $this->webapi = $url;
0152: $n = 1;
0153:
0154: //PEAR::XML_Unserializer
0155: if (class_exists('XML_Unserializer')) {
0156: $xml = new XML_Unserializer();
0157: $xml_data = file_get_contents($url);
0158: $xml->unserialize($xml_data);
0159: $arr = $xml->getUnserializedData();
0160: //レスポンス・チェック
0161: if (preg_match('/ok/i', $arr['status']) == 0) return 0;
0162: //位置情報
0163: if (isset($arr['result']['geometry'])) {
0164: $items[$n]['latitude'] = $arr['result']['geometry']['location']['lat'];
0165: $items[$n]['longitude'] = $arr['result']['geometry']['location']['lng'];
0166: $items[$n]['address'] = $arr['result']['formatted_address'];
0167: $n++;
0168: } else {
0169: foreach ($arr['result'] as $val) {
0170: $items[$n]['latitude'] = $val['geometry']['location']['lat'];
0171: $items[$n]['longitude'] = $val['geometry']['location']['lng'];
0172: $items[$n]['address'] = $val['formatted_address'];
0173: $n++;
0174: }
0175: }
0176: $xml = NULL;
0177:
0178: //PHP4用; DOM XML利用
0179: } else if ($this->isphp5over() == FALSE) {
0180: if (($dom = $this->read_xml($url)) == NULL) return FALSE;
0181: $gr = $dom->get_elements_by_tagname('GeocodeResponse');
0182: //レスポンス・チェック
0183: $res = $gr[0]->get_elements_by_tagname('status');
0184: if (preg_match("/ok/i", $res[0]->get_content()) == 0) return 0;
というのは、PHP4 ではクラス DOMElement を使って XML パーシングしているのだが、これが "\Windows\System32\" に配置した "iconv.dll" をロードするためである。 bamcompile は、PHP エクテンション以外の DLL は配置できないのだ。
また、PHP4 には XML をパーシングするための関数 xml_parse があるのだが、これが使いにくい。

そこで、PEAR にある XML_Unserializer を利用することにした。PEAP::XML_Unserializer は、XML ファイルの内容を連想配列に展開してくれる。

PEAR のインストール方法は公式サイト「PEAR パッケージマネージャの取得とインストール」を参照していただくとして、ここで必要なのは、"PEAR.php", "Parser", "Unserializer" の 3 つだけである。
これを下記のように配置する。
address2geowin │ address2geowin.bcp └─address2geowin │ address2geowin.phpw │ address2geowin.rc │ address2geowin.ico │ PEAR.phpw │ Unserializer.php │ Parser.php │ php_mbstring.dll │ php_winbinder.dll ├─include │ wb_generic.inc.php │ wb_resources.inc.php │ wb_windows.inc.php │ winbinder.php └─icon address2geowin.ico

メソッド getURL_GeoCodeAPI_V3 は「PHP で Google等を利用して住所から緯度・経度を求める」で紹介したものと同じで、API の結果となる XML の URL を取得する。
関数 file_get_contents で XML ファイルを読み込み、メソッド unserialize を使ってアンシリアライズする。アンシリアライズした結果を配列 $arr に代入するのに、メソッド getUnserializedData を利用する。
あとは、API が返す XML 構造にしたがって配列 $arr を解釈していけばいい。

注意すべき点は、result が複数ある場合には $arr['result'][0]['geometry'],$arr['result'][1]['geometry'],$arr['result'][2]['geometry']‥‥のように代入されるが、result が 1 つしかない場合には $arr['result']['geometry'] となる点だ。
ここでは if 文で条件分岐して、どちらの場合も読み込めるようにしてある。
サンプル・プログラムの解説: 緯度・経度を表示
0104: /**
0105: * 緯度・経度を表示
0106: * @param int $window ウィンドウID
0107: * @return string なし
0108: */
0109: function put_geometry($window) {
0110: $pgc = new pahooGeoCode();
0111:
0112: $items = array();
0113: $query = wb_get_text(wb_get_control($window, IDC_ADDRESS_EDIT));
0114: $query = sjis2internal($query);
0115: list($n, $url) = $pgc->searchPoint2($query);
0116: if (! $pgc->iserror()) {
0117: for ($i = 1; $i <= $n; $i++) {
0118: list($items[$i]['latitude'], $items[$i]['longitude'], $items[$i]['address']) = $pgc->getPoint($i);
0119: }
0120: $msg = $items[1]['address'];
0121: $lat = lat2dgree($items[1]['latitude']);
0122: $lng = lng2dgree($items[1]['longitude']);
0123: } else {
0124: $msg = '**検索失敗**';
0125: $lat = '';
0126: $lng = '';
0127: }
0128: wb_set_text(wb_get_control($window, IDC_MSG_LABEL), internal2sjis($msg));
0129: wb_set_text(wb_get_control($window, IDC_LAT_EDIT), $lat);
0130: wb_set_text(wb_get_control($window, IDC_LNG_EDIT), $lng);
0131: unset($items);
0132:
0133: $pgc = NULL;
0134: }
コンパイル
"address2geowin.exe" は、DLL 不要で、単独で動作する EXE プログラムである。
参考サイト
- PHP で Google等を利用して住所から緯度・経度を求める:ぱふぅ家のホームページ
- Google Geocoding API V3
- php で xml を出力して受け取る方法
- XML/Serializer で xml に属性値をセットする:BlueEyesBlue
そこで今回は、「PHP で Google等を利用して住所から緯度・経度を求める」で紹介した「Google Geocoding API V3」「ジオどす II」を利用し、住所や駅名から緯度・経度を求める Windows アプリケーションを作ってみることにする。