KMLというのは三次元地理空間情報を管理するXMLフォーマットです。このフォーマットの代表例として、Googleマップのマイマップが対応しています。位置情報データをイチから作るのは難しいですが、Googleマップのマイマップで作れると敷居が下がることでしょう。
今回はKMLを解析してmBaaSに取り込む方法を紹介します。
KMLとKMZ
Googleマップからダウンロードできるフォーマットとして、KMLとKMZがあります。KMLは都度ダウンロードして使う形式で、KMZはKMLがダウンロードできるURLが記述されたファイルがZip圧縮されています。今回はこのKMZファイルをダウンロード&解凍して使います。
内容は以下のようになっています。
<?xml version="1.0" encoding="UTF-8"?> <kml xmlns="http://www.opengis.net/kml/2.2"> <Document> <name>AAAA</name> <description>https://example.com/?utm_source=www.google.co.jp</description> <NetworkLink> <name>AAAA</name> <Link> <href>http://www.google.com/maps/d/u/0/kml?mid=XXX</href> </Link> </NetworkLink> </Document> </kml>
この NetworkLink に記述されているURLにアクセスすると、KMLファイルがダウンロードできます。しかし、このファイルはアイコンファイルと一緒にZip圧縮されていますので注意が必要です。
コンテンツのダウンロード
まずファイルをダウンロードします。使うのは Superagent です(JavaScript SDKでも使われているので)。単純にアクセスすると文字列で返ってきてしまうので、 .buffer(true).parse(request.parse.image)
を付けてアクセスします。
const url = 'http://www.google.com/maps/d/u/0/kml?mid=XXX'; const response = await request.get(url).buffer(true).parse(request.parse.image);
このレスポンスをUnzipします。
const zip = new JSZip(response.body, {base64: false, checkCRC32: true});
doc.kml というパスでコンテンツが入っていますが、この内容が文字化けしているケースがあります(日本語を使っている場合)。そこでiconvを使って文字化けを解消します。
const buf = new Buffer(zip.files['doc.kml']._data, 'binary'); const retStr = iconv.decode(buf, 'utf-8');
そしてKMLを解析し、JSONベース(GeoJSON)にします。
const kml = new DOMParser().parseFromString(retStr); const converted = tj.kml(kml);
後は順番にmBaaSに登録するだけです。
const promises = []; for (const feature of converted.features) { promises.push(registerSpace(feature)); } const results = await Promise.all(promises); console.log('インポート完了');
mBaaSに登録する
mBaaSに登録する処理は例えば以下のようになります。重複登録をチェックします。
const registerSpace = async (feature) => { const id = parseInt(feature.properties.ID); const result = await Venue .equalTo('id', id) .count() .fetchAll(); if (result.count === 1) { return true; } // 後述 }
次に位置情報は ncmb.GeoPoint を使ってオブジェクトを生成します。後は必要な情報をセットして保存します。
const venue = new Venue; const point = new ncmb.GeoPoint(feature.geometry.coordinates[1], feature.geometry.coordinates[0]); await venue .set('point', point) .set('name', feature.properties.name) .set('id', id) .set('address', `${feature.properties['住所']} ${feature.properties['ビル名']}`) .save(); return venue; }
まとめ
mBaaSに取り込んでしまえば、より細かく情報を絞り込んだり、メタ情報を追加して管理もできるようになります。位置情報の細かい設定をmBaaS上で行うのは大変ですが、Googleマップを使うことでデータ作成は簡単にできるでしょう。