サンプル・プログラム
解説:準備
  23: * 出典: 農研機構 (https://aginfo.cgk.affrc.go.jp/)
  24: * YOLP 標高API
  25: * YOLP 気象情報API
  26: * YOLPコンテンツジオコーダAPI
  27: * Yahoo! JavaScriptマップ【廃止】
  28: * HeartRails Geo API
  29: * OSM Nominatim
WebAPI「ジオどすII」ではAPIキーが必要になる。これは https://geodosu.com/user/register から無料で入手することができる。このAPIキーの値は定数 APIKEY_GEODOS にあらかじめ設定しておく。
また、今回は使用しないが、Yahoo! JAPAN Webサービスを利用する場合は、アプリケーションIDを https://account.edit.yahoo.co.jp/registration から無償取得し、定数 YAHOO_APPLICATION_ID に設定しておく。
解説:XMLパーシング
 107:
 108: return $version[0] >= 5 ? TRUE : FALSE;
 109: }
 110:
 111: /**
 112: * PHP7以上かどうか検査する
 113: * @return bool TRUE:PHP5以上/FALSE:PHP5未満
 114: */
 115: function isphp7over() {
 116: $version = explode('.', phpversion());
 117:
 118: return $version[0] >= 7 ? TRUE : FALSE;
 119: }
 120:
 121: /**
 122: * 無効な証明書サイトからXML取得できるようにする
 123: * @param なし
 124: * @return なし
 125: */
 126: function unknown_certificate() {
 127: $context = array(
 128: 'ssl' => array(
 129: 'verify_peer' => FALSE,
 130: 'verify_peer_name' => FALSE,
 131: )
 132: );
 133: libxml_set_streams_context(stream_context_create($context));
 134: }
 135:
 136: // GoogleMaps API Geocoding =================================================
 137: /**
 138: * 指定XMLファイルを読み込んでDOMを返す
 139: * @param string $xml XMLファイル名
 140: * @return object DOMオブジェクト/NULL 失敗
 141: */
 142: function read_xml($xml) {
 143: if ($this->isphp5over()) return NULL;
 144: if (($fp = fopen($xml, 'r')) == FALSE) return NULL;
 145:
 146: //いったん変数に読み込む
 147: $str = fgets($fp);
 148: $str = preg_replace('/UTF-8/', 'utf-8', $str);
 149:
 150: while (! feof($fp)) {
 151: $str = $str . fgets($fp);
 152: }
 153: fclose($fp);
 154:
 155: //DOMを返す
 156: $dom = domxml_open_mem($str);
 157: if ($dom == NULL) {
 158: echo "\n>Error while parsing the document - " . $xml . "\n";
 159: exit(1);
 160: }
 161:
 162: return $dom;
 163: }
 164:
 165: /**
 166: * GoogleMaps API Geocodingのformatted_addressから国名、郵便番号を除く
 167: * @param string $formatted_address 国名、郵便番号付き住所
 168: * @return string 住所のみ
 169: */
 170: function trimAddress($formatted_address) {
 171: $pat1 = '/〒[0-9\-]+\s(.+)$/ui';
 172: $pat2 = '/.+、(.+)$/ui';
 173:
 174: if (preg_match($pat1, $formatted_address, $arr) > 0) {
 175: $res = $arr[1];
 176: } else if (preg_match($pat2, $formatted_address, $arr) > 0) {
 177: $res = $arr[1];
 178: } else {
 179: $res = $formatted_address;
 180: }
 181:
 182: return $res;
 183: }
 184:
というのは、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文で条件分岐して、どちらの場合も読み込めるようにしてある。
サンプル・プログラムの解説: 緯度・経度を表示
 104: /**
 105: * 緯度・経度を表示
 106: * @param int $window ウィンドウID
 107: * @return string なし
 108: */
 109: function put_geometry($window) {
 110: $pgc = new pahooGeoCode();
 111:
 112: $items = array();
 113: $query = wb_get_text(wb_get_control($window, IDC_ADDRESS_EDIT));
 114: $query = sjis2internal($query);
 115: list($n, $url) = $pgc->searchPoint2($query);
 116: if (! $pgc->iserror()) {
 117: for ($i = 1; $i <= $n; $i++) {
 118: list($items[$i]['latitude'], $items[$i]['longitude'], $items[$i]['address']) = $pgc->getPoint($i);
 119: }
 120: $msg = $items[1]['address'];
 121: $lat = lat2dgree($items[1]['latitude']);
 122: $lng = lng2dgree($items[1]['longitude']);
 123: } else {
 124: $msg = '**検索失敗**';
 125: $lat = '';
 126: $lng = '';
 127: }
 128: wb_set_text(wb_get_control($window, IDC_MSG_LABEL), internal2sjis($msg));
 129: wb_set_text(wb_get_control($window, IDC_LAT_EDIT), $lat);
 130: wb_set_text(wb_get_control($window, IDC_LNG_EDIT), $lng);
 131: unset($items);
 132:
 133: $pgc = NULL;
 134: }
コンパイル
"address2geowin.exe" は、DLL不要で、単独で動作するEXEプログラムである。
参考サイト
- PHPでGoogle等を利用して住所から緯度・経度を求める:ぱふぅ家のホームページ
- Google Geocoding API V3
- phpでxmlを出力して受け取る方法
- XML/Serializerでxmlに属性値をセットする:BlueEyesBlue
そこで今回は、「PHPでGoogle等を利用して住所から緯度・経度を求める」で紹介した「Google Geocoding API V3」「ジオどすII」を利用し、住所や駅名から緯度・経度を求めるWindowsアプリケーションを作ってみることにする。