園田 誠(そのだ まこと)

 地図というのはどうしてこうも男心をくすぐるんでしょうか。一通り知り合いの家あたりを見終わると,目に付いた道をまっすぐたどってどこまでいくのか見てみたくなります。そして突き当たると,この国道にも起点や終点があったんだなとか変なことに感動してみたり。プログラムなんかしなくてもこれはこれで楽しめるのかもしれま…いや,ちゃんと記事書きます。ごめんなさい。1965年生まれ。愛知県名古屋市出身のフリーライター。

 前回に引き続き,Yahoo!提供のWebサービスの活用法を説明します。今回サンプルとして作るのは「Yahoo!ローカルサーチWebサービス」(以下ローカルサーチと略)を利用したアプリケーションです。

XML返答型Webサービス

 ローカルサーチは,住所や郵便番号,学校や主要な建物(ランドマーク)をキーワードとした検索機能を提供するサービスです。サーバーは,指定されたキーワードの緯度/経度情報や,その周辺にある施設の情報を返してきます。

 前回のサンプルで「うちの近所の地図を出したいけど緯度や経度を指定しろと言われてもわからないじゃないか」という疑問が出てきたわけですが,どうやらローカルサーチと組み合わせることで,欲しい部分の地図を表示させることもできそうです。

 地図情報Webサービスでは,こちらの指定に対して直接地図が表示されました。しかしローカルサーチではクライアント(こちら側)からの問い合わせに対して,サーバーはXMLで返答してきます。前回のように地図が出るわけでも整形されたHTMLが出るわけでもありません。クライアント側でXMLを処理しないと期待するような表示結果は得られません。

 あれこれ理屈を言うよりも実際に見ていただくのが早いでしょう。ブラウザで以下のURLを開いてみてください。

http://api.map.yahoo.co.jp/LocalSearchService/V1/LocalSearch?appid=xxxxxxxx&p=1500001&category=zipcode

 xxxxxxxxの部分にはあなたのアプリケーションIDが入ります(アプリケーションIDについては前回の記事を参照してください)。

 このURLは,150-0001という郵便番号を検索対象としてローカルサーチWebサービスを呼び出しています。今の段階では?以降の引数がどんな意味を持つかといった部分は無視していただいてかまいません。

図1●郵便番号150-0001でローカルサーチを呼び出したときの返答内容。生のXMLが返ってくる
図1●郵便番号150-0001でローカルサーチを呼び出したときの返答内容。生のXMLが返ってくる
[画像のクリックで拡大表示]

 XMLの内容はおよそ見たままで,特に説明は必要ないでしょう。<Address>の部分が郵便番号に対応する住所です。<DatumTky97>と<DatumWgs84>のところにそれぞれ<Lat>と<Lon>という要素があって緯度と経度になっています。

 <DatumTky97>と<DatumWgs84>は,それぞれ日本測地系と世界測地系の意味です。若干緯度と経度に差があります。実測で400m前後の差が生じます。Yahoo!の地図情報は,日本測地系のほうが期待する結果に近いようです。

XMLをJavaScriptで処理する

 XMLで結果が返ってくるとわかったところで,それを体裁を整えて表示するというステップに進みましょう。XMLをHTMLなどの体裁の整ったドキュメントに取り込む方法はいくつかあります。例えば,PerlやPHPなどのサーバー・サイドで動作する言語で処理してページを生成するという方法があります。今回は,クライアントで気軽に試せるJavaScriptを使うことにします。

 JavaScriptでXMLを扱うには,DOMと呼ぶオブジェクトを使用します。これはWindowsとInternet Explorer(IE)に強く依存しますので,サンプルはWindowsとIEの組み合わせで試してください。Firefoxなどのブラウザでは動作しません。ご注意ください。

 また作成したHTMLをインターネット上のサーバーにアップロードした場合にも,セキュリティの関係で正しく結果が出ない場合があるようです。作成したサンプルはデスクトップなどローカルに保存して,ダブルクリックで実行して確認してみてください。

 なお,IE以外のブラウザを対象に,JavaScriptでXML処理を行うことも技術的には可能です。ただしその場合は,JavaScriptの記述が異なるため,いったんブラウザを識別してページを分けるといった工夫が必要になります。コードが煩雑化,複雑化してしまうのと,ユーザーにも負担をかける(例えば「IEの人はこちら,Firefoxの人はこちら」といった選択を要求される)ので,ブラウザの差異を吸収するにはサーバー・サイド処理を行ったほうがいいでしょう。当然ながら,サーバー側でPHPやJavaを使ったプログラムを作成する必要があります。

郵便番号から地図を表示する

 これから作成するサンプルは,郵便番号の入力欄を備えており,入力された郵便番号から緯度と経度を求めて,その情報を基に前回やった地図表示を行うというものです。

 現在,郵便番号は,7桁の数字で市区町村名(何丁目の手前まで)を示すようになっています。場所によっては建物や企業までを示します。ただし,ローカルサーチのデータベースに郵便番号のすべてが入っているわけではないようです。例えば,日経BP社の「108-8646」という郵便番号はローカルサーチでは引けません。

図2●サンプル・プログラムの実行画面
図2●サンプル・プログラムの実行画面。入力された郵便番号から市区町村と緯度経度を検索して,地図画面を表示する。緯度や経度はわからなくても,郵便番号ならば情報を得やすいので,格段に使い勝手が良くなる

 ソース・ファイル(JavaScriptを記述したHTMLファイル)は,文字コードUTF-8で作成してください。これは,この後に実装する住所検索機能に関係があります。

 ファイルはデスクトップに保存してダブルクリックで起動します。もし何も表示されない(真っ白なページになってしまう)場合は,IEのメニュー[表示]-[エンコード]で,「Unicode(UTF-8)」を選択してください。

図3●真っ白で何も表示されないときは,エンコードを「Unicode(UTF-8)」に設定
図3●真っ白で何も表示されないときは,エンコードを「Unicode(UTF-8)」に設定

 UTF-8で保存できるエディタをお持ちでない場合は,

<meta http-equiv="Content-Type" content="text/html;charset=utf-8">
の部分を
<meta http-equiv="Content-Type" content="text/html;charset=shift_jis">
に書き換えてシフトJISで保存してください。

 シフトJISで作成してもXML内の文字コード(もともとのXMLはUTF-8で戻ってきます)は,DOMが文字コードを書き換えてくれるので,住所部分で文字化けは発生しません。一応これでも動きます。ただし,後々の住所検索など日本語を送信する場合にはUTF-8である必要があり,かつURLエンコードされていなくてはなりません。

図4●Windows付属のメモ帳で作成して保存する場合は「名前を付けて保存」で文字コードの指定をUTF-8にする
図4●Windows付属のメモ帳で作成して保存する場合は「名前を付けて保存」で文字コードの指定をUTF-8にする
[画像のクリックで拡大表示]

 プログラムは,リスト1のようになります。

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>ローカルサーチ</title>

        ・
        ・
        ・
リスト1●郵便番号から地図を表示するサンプル・プログラム。xxxxxxxxには取得したあなたがアプリケーションIDを記述する

 xml_doc = new ActiveXObject("Microsoft.XMLDOM");という宣言でDOMオブジェクトを生成しています。XMLドキュメントは,DOMを介することでプログラムから値の取得などが行えるようになります。データとなるXMLは以下のコードで取得しています。

xml_doc.load("http://api.map.yahoo.co.jp/LocalSearchService/V1/LocalSearch?appid=xxxxxxxx&p=" +zipcode + "&category=zipcode");

 括弧の中にはURLが書かれています。このURLは,冒頭で生のXMLを見たのと同じものです。郵便番号の部分だけは,フォームから送信された郵便番号を代入しています。初回起動などで郵便番号が送信されてこなかった場合には,初期値として設定されている郵便番号を利用します。

 http://api.map.yahoo.co.jp/LocalSearchService/V1/LocalSearchまでの部分は固定です。?以降がローカルサーチ用の引数指定です。「category=」で何を検索するのかを指定します。指定できるカテゴリーは次の通りです。

address 住所を対象に検索
zipcode 郵便番号を対象に検索
landmark 施設(役所,学校,病院,郵便局など)を対象に検索
station 駅を対象に検索
courpon Yahoo!クーポンを対象に検索

 今回使用したのはzipcodeです。「p=」の後に,指定したカテゴリーに対する検索語句を記述します。今回は郵便番号の数値を送ります。“123-4567”のような書き方でも“1234567”というハイフンなしでも受け付けてもらえるようです。仮に「cvategory=address」とすれば住所を直接検索することもできます。この場合は「p=」の部分に住所を文字列として送信することになります。

 XMLは,階層構造になっていて,それぞれがノードと呼ばれる枝の単位で構成されます。今回処理に必要なのは緯度と経度だけです。緯度と経度は<LocalSearchResult>の子ノード<Item>の,さらに下の<DatumTky97>の子ノードになっています。

 該当部分にたどり着くまでが,whileループの中のwhileループという,ややこしいネストの中に存在していますが,それぞれのプログラム・コードは数行程度なので,それほど難しくはありません。なんとなく流れを追って読み切ってください。

 DOMの使い方を習得するということでは,本来ならば1階層(子ノードなし)のケースから順番に解説したいところですが,今回はXML+DOMの学習が主旨ではありませんのでバサっと省略させていただきます。ごめんなさい。

 結果的に緯度と経度が得られたら,取得した緯度と経度を渡して地図を描画させます。第1回の地図表示と比較すると格段に地図システムっぽくなってきました。