ニフクラ mobile backend(mBaaS)お役立ちブログ

スマホアプリ開発にニフクラ mobile backend(mBaaS)。アプリ開発に役立つ情報をおとどけ!

地図アプリのベースに。KMLをmBaaSに取り込む

f:id:mbaasdevrel:20180705171029p:plain

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マップを使うことでデータ作成は簡単にできるでしょう。

中津川 篤司

中津川 篤司

NCMBエヴァンジェリスト。プログラマ、エンジニアとしていくつかの企業で働き、28歳のときに独立。 2004年、まだ情報が少なかったオープンソースソフトの技術ブログ「MOONGIFT」を開設し、毎日情報を発信している。2013年に法人化、ビジネスとエンジニアを結ぶDXエージェンシー「DevRel」活動をスタート。