User:Tatata/ksj2osm-airport.pl

From OpenStreetMap Wiki
Jump to navigation Jump to search

This perl script convert KSJ2 airport data xml file to osm xml file. (ja)このperlスクリプトは国土数値情報(空港データ)のxmlファイルをosmのxmlファイルに変換します。


Preparation

(ja)準備

  • Installation of JOSM (a java program; needs J2SE SDK or JRE). (ja)JOSMの導入(javaプログラムなので実行にはJ2SE SDK或いはJREが必要。)
  • Installation of perl. You can download ActivePerl from ActiveState site (free of charge). (ja)perlの導入。ActiveStateのサイトからActivePerlをでダウンロードできる(無料)。
  • Save the code below as a file with proper name. (e.g. ksj2osm-airport.pl) (ja)適切なファイル名を付けて下のソースコードを保存する。(例えばksj2osm-airport.plなど。)

How to convert the data

(ja)変換手順

  • Download KSJ2 airport data decompress from zip file to xml file. (ja)国土数値情報(空港データ)をダウンロードし、zipファイルを解凍してxmlファイルにする。
  • Put the xml file on the same directory of the script. (ja)xmlファイルをスクリプトと同じディレクトリに置く。
  • Open the perl script by editor program, edit the initial values of $target_na3 to specify airport name with UTF-8 characters (you can copy and paste from list) and $airport_type (0 or 1) to specify airport type, and then save the script. (ja)このperlスクリプトをエディタープログラムで開き、$target_na3の初期値にUTF-8の文字による空港名(このリストからコピペ可)、$airport_typeの初期値に空港のタイプ (0又は1) を書き込んでスクリプトを保存する。
  • Open command prompt window and run the script on the directory where you put the script and xml file. Output files (ksj2osm-airport.osm, ksj2osm-airport.log) will be created on the same directory. (ja)コマンドプロンプトを開いて、スクリプトとxmlファイルを置いたディレクトリでスクリプトを実行する。出力ファイル (ksj2osm-airport.osm, ksj2osm-airport.log) は同じディレクトリに作成される。
  • Open ksj2osm-airport.osm by JOSM, check and edit the data (see notes below), and then upload to server. (ja)JOSMでksj2osm-airport.osmを開いてデータの確認や編集を行い(下の注意を参照)、それからサーバーにアップロードする。

Notes

(ja)注意

  • The coordinate of the node which is tagged with "aeroway=aerodrome", is calculated values as the middle between the maximum latitude of the airport site and the minimum latitude and the middle between the maximum longitude and the minimum longitude. (ja)"aeroway=aerodrome"タグが付けられたノードの座標は、空港敷地の最大の緯度と最小の緯度の中間点及び最大の経度と最小の経度の中間点として計算された値です。
  • KSJ2 airport data doesn't have information below, so you need to input them manually into the node which is tagged with "aeroway=aerodrome". (ja)国土数値情報の空港データには以下の情報が無いので、"aeroway=aerodrome"タグが付けられたノードについてはそれらを手入力する必要があります。

Code

As of 2009-05-26.
Bugfix 2010-04-08




#!/usr/bin/perl

use strict;
use warnings;
# use encoding "utf8"; 
use encoding "utf8", STDOUT => "shiftjis", STDERR => "shiftjis"; # for Windows
use Encode;
use open IO => "utf8";
use XML::Parser;
use XML::Simple;

#####
#
# KSJ2 Airport Data
#
# National-Land Numerical Information (Airport) 2007, MLIT Japan
# 国土数値情報(空港データ)平成19年 国土交通省
#
# Files
#   Input
#     XML file : C28-07.xml
#   Output
#     Osm file : ksj2osm-airport.osm
#     Log file : ksj2osm-airport.log
#
#####

our $file_in = "C28-07";
our $file_name = "ksj2osm-airport";

our $target_na3 = "大阪国際空港"; # airport name (UTF-8) "成田国際空港", "*", ""

our $airport_type = 0;   #  0 : for airport located inland, the area will be tagged with "natural=heath".
                         #  1 : for airport located in/off shore, the area will be tagged with "landuse=landfill".

our $aac_code;
our %airportHash;
our %iac_code;
our @latArray;
our @longArray;
our $negative_id = 0;
our $node_ref;
our %nodes = ();
our $num_airports;
our $num_nodes;
our $num_ways;
our $pref_code;
our %ref_code;
our %timeHash;
our @workArray;
our %workHash;
our $workString;
our $xml_aac;
our $xml_pref;

sub main() {

  my $parser = new XML::Parser(ErrorContext => 3,
                               Handlers => {Init => \&handle_init,
                                            Start => \&handle_start,
                                            Char => \&handle_char,
                                            End => \&handle_end,
                                            Final => \&handle_final});

  $parser->parsefile("$file_in.xml");

}


sub handle_init() {

  open_log();
  get_codelist();

}


sub handle_start() {

  my ($expat, $element, %hash) = @_;
  if ($element eq "jps:TM_Instant" 
    || $element eq "ksj:CF02"
    || $element eq "ksj:ARE"
    || $element eq "ksj:POS"
    || $element eq "ksj:ASI"
    || $element eq "ksj:CF05"     # 調査(1日当りの着陸回数・乗降客数)
    || $element eq "ksj:YS2"      # 調査年(複数年有り)
    || $element eq "jps:GM_Surface"
    || $element eq "jps:GM_CompositeCurve.generator"
    || $element eq "jps:GM_Curve"
    || $element eq "GM_PointRef.point"
    || $element eq "jps:GM_Point") {get_id(@_);}
  $workString = "";                              # add 2009-05-26

}


sub handle_char () {

  my ($expat, $string) = @_;
#  $workString = $string;
#  $workString .= "";                             # mod 2009-05-26
  $workString = $string;                          # mod 2010-04-08
}


sub handle_end() {

  my ($expat, $element) = @_;
  if ($element eq "TM_CalDate.calDate"
    || $element eq "ksj:AAC"
    || $element eq "ksj:COA"
    || $element eq "ksj:IUC"
    || $element eq "ksj:NA3"
    || $element eq "ksj:INP"
    || $element eq "ksj:AD2"
    || $element eq "ksj:DSA"
    || $element eq "ksj:OPT"
    || $element eq "ksj:CLT"
    || $element eq "ksj:REF"
    || $element eq "ksj:RWL"
    || $element eq "ksj:RWW"
    || $element eq "ksj:LFD"
    || $element eq "ksj:NPD"
    || $element eq "DirectPosition.coordinate") {get_element(@_);}
  elsif ($element eq "jps:TM_Instant") {add_time();}
#  elsif ($element eq "ksj:CF02") {add_airport();}                          # del 2010-04-08
#  elsif ($element eq "ksj:ARP") {add_refpoint();}                          # del 2010-04-08
#  elsif ($element eq "ksj:ATB") {add_terminal();}                          # del 2010-04-08
  elsif ($element eq "ksj:CF03") {add_refpoint();}                          # add 2010-04-08
  elsif ($element eq "ksj:CF04") {add_terminal(); add_airport();}           # add 2010-04-08
  elsif ($element eq "ksj:RNW") {add_runway();}
  elsif ($element eq "ksj:CF05") {add_survey();}
  elsif ($element eq "jps:GM_Surface") {add_curve();}
  elsif ($element eq "jps:GM_Curve") {add_point();}
  elsif ($element eq "jps:GM_Point") {replace_point();}

}


sub handle_final() {

  my $time = localtime(time);
  print LOG "***** Process of infile : End $time\n";
  print "***** Process of infile : End $time\n";

  print LOG "*****\n";
  foreach my $item(keys %airportHash) {
    print LOG "* 1st key: $item\n";
    foreach my $item2(keys %{$airportHash{$item}}) {
        print LOG "** 2nd key: $item2, value: $airportHash{$item}{$item2}\n";
    }
    print LOG "*****\n";
  }

  create_osm();

  close_log();

}


sub open_log() {

  my $time = localtime(time);
  open(LOG, ">$file_name.log");
  print LOG "***** KSJ2 Airport Data 2007 : Start $time\n";
  print "***** KSJ2 Airport Data 2007 : Start $time\n";
  print LOG "***** Target : $target_na3, airport type = $airport_type\n";
  print "***** Target : $target_na3, airport type = $airport_type\n";

}


sub close_log() {

  my $time = localtime(time);
  print LOG "***** Done!: End $time\n";
  close LOG;
  print "***** Done!: End $time\n";

}


sub get_codelist() {

  # AdminAreaCd.xml 行政コード

  $aac_code = XMLin($xml_aac, keyattr => ["code"]);

  # InstallAdminCd-v1_1.xml 設置者・管理者コード
  # 「国土数値情報(コードリスト)平成19年 国土交通省」
  # http://nlftp.mlit.go.jp/ksj/jpgis/codelist/InstallAdminCd-v1_1.html

  my %hash = (
    "1" => "国土交通大臣",
    "2" => "防衛大臣",
    "3" => "米軍",
    "4" => "公団",
    "5" => "都道府県",
    "6" => "市町村",
  );
  %iac_code = %hash;

  # RegularFlightCd.xml 定期便の有無コード
  # 「国土数値情報(コードリスト)平成19年 国土交通省」
  # http://nlftp.mlit.go.jp/ksj/jpgis/codelist/RegularFlightCd.html

  %hash = (
    "1" => "ジェット定期便が就航している場合",
    "2" => "プロペラ定期便が就航している場合",
    "3" => "定期便が就航していない場合",
  );
  %ref_code = %hash;

  # PrefCode.xml 都道府県コード

  $pref_code = XMLin($xml_pref, keyattr => ["code"]);

}


sub get_id() {

  my ($expat, $element, %hash) = @_;
  if ($element eq "ksj:ARE" ) {
    if (exists($hash{"idref"})) {
      $workHash{"ARE"} = $hash{"idref"};
    }
    else {
      print LOG "* idref not found in element ksj:ARE.\n";
      print "* idref not found in element ksj:ARE.\n";
      while (my ($key, $value) = each(%hash)) {
        print LOG "key: $key , value: $value \n";
        print "key: $key , value: $value \n";
      }
      die "idref not found in element ksj:ARE.";
    }
  }
  elsif ($element eq "ksj:POS" ) {
    if (exists($hash{"idref"})) {
      $workHash{"POS"} = $hash{"idref"};
    }
    else {
      print LOG "* idref not found in element ksj:POS.\n";
      print "* idref not found in element ksj:POS.\n";
      while (my ($key, $value) = each(%hash)) {
        print LOG "key: $key , value: $value \n";
        print "key: $key , value: $value \n";
      }
      die "idref not found in element ksj:POS.";
    }
  }
  elsif ($element eq "ksj:ASI" ) {       # 調査(1日当りの着陸回数・乗降客数)
    if (exists($hash{"idref"})) {        # 調査年毎に複数有り
      if (exists($workHash{"survey"})) {
        $workHash{"survey"} .= ",";
      }
      $workHash{"survey"} .= $hash{"idref"};
    }
    else {
      print LOG "* idref not found in element ksj:ASI.\n";
      print "* idref not found in element ksj:ASI.\n";
      while (my ($key, $value) = each(%hash)) {
        print LOG "key: $key , value: $value \n";
        print "key: $key , value: $value \n";
      }
      die "idref not found in element ksj:ASI.";
    }
  }
  elsif ($element eq "ksj:YS2" ) {       
    if (exists($hash{"idref"})) {        
      $workHash{"YS2"} = $hash{"idref"};
    }
    else {
      print LOG "* idref not found in element ksj:YS2.\n";
      print "* idref not found in element ksj:YS2.\n";
      while (my ($key, $value) = each(%hash)) {
        print LOG "key: $key , value: $value \n";
        print "key: $key , value: $value \n";
      }
      die "idref not found in element ksj:YS2.";
    }
  }
  elsif ($element eq "jps:GM_CompositeCurve.generator" ) {
    if (exists($hash{"idref"})) {
      $workHash{"CompositeCurve"} = $hash{"idref"};
    }
    else {
      print LOG "* idref not found in element jps:GM_CompositeCurve.generator.\n";
      print "* idref not found in element jps:GM_CompositeCurve.generator.\n";
      while (my ($key, $value) = each(%hash)) {
        print LOG "key: $key , value: $value \n";
        print "key: $key , value: $value \n";
      }
      die "idref not found in element jps:GM_CompositeCurve.generator.";
    }
  }
  elsif ($element eq "GM_PointRef.point" ) {
    if (exists($hash{"idref"})) {
      if (exists($workHash{"points"})) {
        $workHash{"points"} .= ",";
      }
      $workHash{"points"} .= $hash{"idref"};
    }
    else {
      print LOG "* id not found in element GM_PointRef.point.\n";
      print "* id not found in element GM_PointRef.point.\n";
      while (my ($key, $value) = each(%hash)) {
        print LOG "key: $key , value: $value \n";
        print "key: $key , value: $value \n";
      }
      die "id not found in element GM_PointRef.point.";
    }
  }
  else {
    if (exists($hash{"id"})) {
      $workHash{"id"} = $hash{"id"};
    }
    else {
      print LOG "* id not found in element $element.\n";
      print "* id not found in element $element.\n";
      while (my ($key, $value) = each(%hash)) {
        print LOG "key: $key , value: $value \n";
        print "key: $key , value: $value \n";
      }
      die "id not found in element $element";
    }
  }
}


sub get_element() {

  my ($expat, $element) = @_;
  if ($element eq "TM_CalDate.calDate" ) {$workHash{"time"} = $workString;}
  elsif ($element eq "ksj:AAC" ) {
    $workString = sprintf("%05d", $workString);
    $workHash{"AAC"} = $workString;
    my $str = $aac_code->{'ksjc:C002'}->{'codelabel'}->{$workString}->{'label'};
    unless ($str) { 
      $str = substr($workString, 0, 2);
      $str = $pref_code->{'ksjc:C001'}->{'codelabel'}->{$str}->{'label'};
      $str .= ", *";
    }
    $workHash{"AAC_label"} = $str;
  }
  elsif ($element eq "ksj:INP" ) {
    $workHash{"INP"} = $workString;
    $workHash{"INP_label"} = $iac_code{$workString};
  }
  elsif ($element eq "ksj:AD2" ) {
    $workHash{"AD2"} = $workString;
    $workHash{"AD2_label"} = $iac_code{$workString};
  }
  elsif ($element eq "ksj:REF" ) {
    $workHash{"REF"} = $workString;
    $workHash{"REF_label"} = $ref_code{$workString};
  }
  elsif ($element eq "ksj:COA" ) {$workHash{"COA"} = $workString;}
  elsif ($element eq "ksj:IUC" ) {$workHash{"IUC"} = $workString;}
  elsif ($element eq "ksj:NA3" ) {$workHash{"NA3"} = $workString;}
  elsif ($element eq "ksj:DSA" ) {$workHash{"DSA"} = $workString;}
  elsif ($element eq "ksj:OPT" ) {$workHash{"OPT"} = $workString;}
  elsif ($element eq "ksj:CLT" ) {$workHash{"CLT"} = $workString;}
  elsif ($element eq "ksj:RWL" ) {$workHash{"RWL"} = $workString;}
  elsif ($element eq "ksj:RWW" ) {$workHash{"RWW"} = $workString;}
  elsif ($element eq "ksj:LFD" ) {$workHash{"LFD"} = $workString;}
  elsif ($element eq "ksj:NPD" ) {$workHash{"NPD"} = $workString;}
  elsif ($element eq "DirectPosition.coordinate" ) {
    if (exists($workHash{"points"})) {
      $workHash{"points"} .= ",";
    }
    $workHash{"points"} .= $workString;
  }
  $workString = "";                              # add 2009-05-26
}


sub add_time() {
  $timeHash{$workHash{"id"}} = $workHash{"time"};
  %workHash = ();
}


sub add_airport() {

  if ($target_na3 eq $workHash{"NA3"} || $target_na3 eq "*" || $target_na3 eq "") {

    while (my ($key, $value) = each(%workHash)) {
      $airportHash{$workHash{"id"}}{$key} = $value;
    }
  }
  %workHash = ();
}


sub add_refpoint() {
  $workHash{"ARP"} = $workHash{"POS"};
  delete $workHash{"POS"};
}


sub add_terminal() {
  $workHash{"ATB"} = $workHash{"POS"};
  delete $workHash{"POS"};
}


sub add_runway() {

  if (exists($workHash{"runways"})) {
    $workHash{"runways"} .= ",";
  }
  $workHash{"runways"} .= "$workHash{'RWL'} $workHash{'RWW'}";
  delete $workHash{"RWL"};
  delete $workHash{"RWW"};
}


sub add_survey() {

  my $flag;

  foreach my $item(keys %airportHash) {
    if (exists($airportHash{$item}{"survey"})) {
      $flag = index($airportHash{$item}{"survey"}, $workHash{"id"});
      if ($flag >= 0) {
        $airportHash{$item}{"survey"} =~ s/$workHash{"id"}/$timeHash{$workHash{"YS2"}} $workHash{"LFD"} $workHash{"NPD"}/g; 
      }
    }
  }
  %workHash = ();
}


sub add_curve() {

  foreach my $item(keys %airportHash) {
    if (exists($airportHash{$item}{"ARE"})) {
      if ($airportHash{$item}{"ARE"} eq $workHash{"id"}) {
        $airportHash{$item}{"CompositeCurve"} = $workHash{"CompositeCurve"};
      }
    }
  }
  %workHash = ();
}


sub add_point() {

  foreach my $item(keys %airportHash) {
    if (exists($airportHash{$item}{"CompositeCurve"})) {
      if ($airportHash{$item}{"CompositeCurve"} eq $workHash{"id"}) {
        $airportHash{$item}{"points"} = $workHash{"points"};
      }
    }
  }
  %workHash = ();
}


sub replace_point() {

  foreach my $item(keys %airportHash) {

    if (exists($airportHash{$item}{"points"})) {
      $airportHash{$item}{"points"} =~ s/$workHash{"id"}/$workHash{"points"}/g;
    }

    if (exists($airportHash{$item}{"ARP"})) {
#      $airportHash{$item}{"ARP"} =~ s/$workHash{"id"}/$workHash{"points"}/g;
      $airportHash{$item}{"ARP"} =~ s/^$workHash{"id"}$/$workHash{"points"}/g;      # mod 2010-04-08
    }

    if (exists($airportHash{$item}{"ATB"})) {
#      $airportHash{$item}{"ATB"} =~ s/$workHash{"id"}/$workHash{"points"}/g;
      $airportHash{$item}{"ATB"} =~ s/^$workHash{"id"}$/$workHash{"points"}/g;      # mod 2010-04-08
    }
  }
  %workHash = ();
}


sub create_osm(){

  my $i = 0;

  open(OSM, ">$file_name.osm");
  print OSM "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
  print OSM "<osm version=\"0.5\" generator=\"KSJ2OSM\">\n";

  foreach my $item(keys %airportHash) {
    @workArray = split(/,/, $airportHash{$item}{"points"});
    foreach my $coordinate(@workArray) {
      $i = write_node($i, $item, $coordinate);
    }
    write_way($i, $item);
    $i = 0;
  }

  print OSM "</osm>";
  close OSM;
  printf LOG 
    "***** Airports : %d nodes on %d ways\n"
    , $num_nodes, $num_ways;
  printf LOG 
    "***** Airports : %d nodes tagged as \"aeroway=aerodrome\"\n"
    , $num_airports;
  printf 
   "***** Airports : %d nodes on %d ways\n"
   , $num_nodes, $num_ways;
  printf 
   "***** Airports : %d nodes tagged as \"aeroway=aerodrome\"\n"
   , $num_airports;

}


sub write_node() {

  my ($i, $item, $coordinate) = @_;
  my $node_id = 0;
  my ($lat, $long) = split(/\s/, $coordinate);

  unless (defined($lat) && defined($long)) {
    print LOG "Skip error data : id = $item, coordinate = $coordinate\n";
    print "Skip error data : id = $item, coordinate = $coordinate\n";
    return;
  }
  if (($lat > 90) || ($lat < -90) || ($lat == 0) 
    || ($long > 180) || ($long < -180) || ($long == 0)) {
    print LOG "Skip error data : id = $item, coordinate = $coordinate, lat = $lat, long = $long\n";
    print "Skip error data : id = $item, coordinate = $coordinate, lat = $lat, long = $long\n";
    return;
  }

  push(@latArray, $lat);
  push(@longArray, $long);

  my $tags = "<tag k=\"created_by\" v=\"National-Land-Numerical-Information_MLIT_Japan\"/>";
  $tags .= "<tag k=\"source\" v=\"KSJ2\"/>";
  $tags .= "<tag k=\"source_ref\" v=\"http://nlftp.mlit.go.jp/ksj/jpgis/datalist/KsjTmplt-C28-v1_1.html\"/>";
  $tags .= "<tag k=\"note\" v=\"National-Land Numerical Information (Airport) 2007, MLIT Japan\"/>";
  $tags .= "<tag k=\"note:ja\" v=\"国土数値情報(空港データ)平成19年 国土交通省\"/>";
  $tags .= "<tag k=\"KSJ2:airport_id\" v=\"$airportHash{$item}{'id'}\"/>";
  $tags .= "<tag k=\"KSJ2:ARE\" v=\"$airportHash{$item}{'ARE'}\"/>";
  $tags .= "<tag k=\"KSJ2:CompositeCurve\" v=\"$airportHash{$item}{'CompositeCurve'}\"/>";
  $tags .= "<tag k=\"KSJ2:coordinate\" v=\"$coordinate\"/>";
  $tags .= "<tag k=\"KSJ2:lat\" v=\"$lat\"/>";
  $tags .= "<tag k=\"KSJ2:long\" v=\"$long\"/>";
  $tags .= "<tag k=\"KSJ2:NA3\" v=\"$airportHash{$item}{'NA3'}\"/>";

  if (exists($nodes{"$lat $long"})) {
    $node_id = $nodes{"$lat $long"};
  }
  else {
    $negative_id--;
    $node_id = $negative_id;
    $nodes{"$lat $long"} = $node_id;
    my $node 
      = sprintf("<node id=\"%d\" visible=\"true\" lat=\"%s\" lon=\"%s\">$tags</node>"
      , $node_id, $lat, $long);
    print OSM "$node\n";
    $num_nodes++;
  }

  $node_ref .= sprintf("<nd ref=\"%d\" />", $node_id);
  printf LOG "Node %d: %s, %s\n", $node_id, $lat, $long;
  $i++;
  return $i;

}


sub write_way() {

  my ($i, $item) = @_;
  my $tmp_tags;
  $negative_id--;

  my $tags = "<tag k=\"created_by\" v=\"National-Land-Numerical-Information_MLIT_Japan\"/>";
  $tags .= "<tag k=\"source\" v=\"KSJ2\"/>";
  $tags .= "<tag k=\"source_ref\" v=\"http://nlftp.mlit.go.jp/ksj/jpgis/datalist/KsjTmplt-C28-v1_1.html\"/>";
  $tags .= "<tag k=\"note\" v=\"National-Land Numerical Information (Airport) 2007, MLIT Japan\"/>";
  $tags .= "<tag k=\"note:ja\" v=\"国土数値情報(空港データ)平成19年 国土交通省\"/>";
  $tags .= "<tag k=\"KSJ2:airport_id\" v=\"$airportHash{$item}{'id'}\"/>";
  $tags .= "<tag k=\"KSJ2:ARE\" v=\"$airportHash{$item}{'ARE'}\"/>";
  $tags .= "<tag k=\"KSJ2:CompositeCurve\" v=\"$airportHash{$item}{'CompositeCurve'}\"/>";
  $tags .= "<tag k=\"KSJ2:AAC\" v=\"$airportHash{$item}{'AAC'}\"/>";
  $tags .= "<tag k=\"KSJ2:AAC_label\" v=\"$airportHash{$item}{'AAC_label'}\"/>";
  $tags .= "<tag k=\"KSJ2:AD2\" v=\"$airportHash{$item}{'AD2'}\"/>";
  $tags .= "<tag k=\"KSJ2:AD2_label\" v=\"$airportHash{$item}{'AD2_label'}\"/>";
  $tags .= "<tag k=\"KSJ2:ARP\" v=\"$airportHash{$item}{'ARP'}\"/>";
  $tags .= "<tag k=\"KSJ2:ATB\" v=\"$airportHash{$item}{'ATB'}\"/>";
  $tags .= "<tag k=\"KSJ2:COA\" v=\"$airportHash{$item}{'COA'}\"/>";
  $tags .= "<tag k=\"KSJ2:DSA\" v=\"$airportHash{$item}{'DSA'}\"/>";
  $tags .= "<tag k=\"KSJ2:INP\" v=\"$airportHash{$item}{'INP'}\"/>";
  $tags .= "<tag k=\"KSJ2:INP_label\" v=\"$airportHash{$item}{'INP_label'}\"/>";
  $tags .= "<tag k=\"KSJ2:IUC\" v=\"$airportHash{$item}{'IUC'}\"/>";
  $tags .= "<tag k=\"KSJ2:NA3\" v=\"$airportHash{$item}{'NA3'}\"/>";
  $tags .= "<tag k=\"KSJ2:REF\" v=\"$airportHash{$item}{'REF'}\"/>";
  $tags .= "<tag k=\"KSJ2:REF_label\" v=\"$airportHash{$item}{'REF_label'}\"/>";
  $tags .= "<tag k=\"KSJ2:OPT\" v=\"$airportHash{$item}{'OPT'}\"/>";
  $tags .= "<tag k=\"KSJ2:CLT\" v=\"$airportHash{$item}{'CLT'}\"/>";
#  $tags .= "<tag k=\"KSJ2:points\" v=\"$airportHash{$item}{'points'}\"/>"; # comment out to reduce data size.
  $tags .= "<tag k=\"KSJ2:runways\" v=\"$airportHash{$item}{'runways'}\"/>";
  $tags .= "<tag k=\"KSJ2:survey_year_LFD_NPD\" v=\"$airportHash{$item}{'survey'}\"/>";

  if    ($airport_type == 0) {$tmp_tags = "<tag k=\"natural\" v=\"heath\"/>";}
  elsif ($airport_type == 1) {$tmp_tags = "<tag k=\"landuse\" v=\"landfill\"/>";}
  else                       {$tmp_tags = "<tag k=\"natural\" v=\"heath\"/>";}

  $tmp_tags .= "<tag k=\"fenced\" v=\"yes\"/><tag k=\"layer\" v=\"-3\"/>";

  my $way 
    = sprintf("<way id=\"%d\" action=\"modify\" visible=\"true\">$tmp_tags$node_ref$tags</way>"
    , $negative_id);
  print OSM "$way\n";
  $num_ways++;
  printf LOG 
    "Way %d: %d nodes id=%s NA3=%s\n"
      , $negative_id, $i, $airportHash{$item}{"id"}
      , $airportHash{$item}{"NA3"};
  $node_ref = "";

  @latArray = sort {$a <=> $b} @latArray;
  @longArray = sort {$a <=> $b} @longArray;

  my $lat = pop(@latArray);
  my $long = pop(@longArray);
  $lat += shift(@latArray);
  $long += shift(@longArray);
  $lat /= 2;
  $long /= 2;

  $tmp_tags = "<tag k=\"aeroway\" v=\"aerodrome\"/><tag k=\"layer\" v=\"1\"/>";
  $tmp_tags .= "<tag k=\"icao\" v=\"\"/><tag k=\"iata\" v=\"\"/>";
  $tmp_tags .= "<tag k=\"name\" v=\"$airportHash{$item}{'NA3'} ()\"/><tag k=\"name:en\" v=\"\"/>";
  $tmp_tags .= "<tag k=\"name:ja\" v=\"$airportHash{$item}{'NA3'}\"/><tag k=\"name:ja_rm\" v=\"\"/>";

  $negative_id--;

  my $node 
    = sprintf("<node id=\"%d\" visible=\"true\" lat=\"%s\" lon=\"%s\">$tmp_tags$tags</node>"
    , $negative_id, $lat, $long);
  print OSM "$node\n";
  printf LOG "Node %d: %s, %s (aeroway=aerodrome)\n", $negative_id, $lat, $long;
  print LOG "*****\n";

  $num_airports++;

  @latArray = ();
  @longArray = ();

}


# extracts from AdminAreaCd.xml 行政コード(抜粋)
# 「国土数値情報(コードリスト)平成19年 国土交通省」
# http://nlftp.mlit.go.jp/ksj/jpgis/codelist/codelists.zip

$xml_aac =<<"End";
<?xml version="1.0" encoding="UTF-8"?>
<ksjc:CodeSet xmlns:ksjc="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app-cd" xmlns:jps="http://www.gsi.go.jp/GIS/jpgis/standardSchemas" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app-cd KsjCodelist.xsd">	
 <ksjc:C002>	
     <description>行政コード</description>	
     <codelabel label="北海道札幌市東区" code="01103"/>	
     <codelabel label="北海道函館市" code="01202"/>	
     <codelabel label="北海道釧路市" code="01206"/>	
     <codelabel label="北海道帯広市" code="01207"/>	
     <codelabel label="北海道稚内市" code="01214"/>	
     <codelabel label="北海道紋別市" code="01219"/>	
     <codelabel label="北海道紋別市" code="01219"/>	
     <codelabel label="北海道千歳市" code="01224"/>	
     <codelabel label="北海道奥尻郡奥尻町" code="01367"/>	
     <codelabel label="北海道上川郡東神楽町" code="01453"/>	
     <codelabel label="北海道礼文郡礼文町" code="01517"/>	
     <codelabel label="北海道利尻郡利尻富士町" code="01519"/>	
     <codelabel label="北海道川上郡弟子屈町" code="01665"/>	
     <codelabel label="北海道標津郡中標津町" code="01692"/>	
     <codelabel label="青森県青森市" code="02201"/>	
     <codelabel label="青森県三沢市" code="02207"/>	
     <codelabel label="岩手県花巻市" code="03205"/>	
     <codelabel label="宮城県名取市" code="04207"/>	
     <codelabel label="秋田県秋田市" code="05201"/>	
     <codelabel label="山形県酒田市" code="06204"/>	
     <codelabel label="山形県東根市" code="06211"/>	
     <codelabel label="福島県石川郡玉川村" code="07502"/>	
     <codelabel label="千葉県成田市" code="12211"/>	
     <codelabel label="東京都大田区" code="13111"/>	
     <codelabel label="東京都調布市" code="13208"/>	
     <codelabel label="東京都大島大島町" code="13361"/>	
     <codelabel label="東京都新島新島村" code="13363"/>	
     <codelabel label="東京都神津島神津島村" code="13364"/>	
     <codelabel label="東京都三宅島三宅村" code="13381"/>	
     <codelabel label="東京都八丈島八丈町" code="13401"/>	
     <codelabel label="新潟県佐渡市" code="15224"/>	
     <codelabel label="富山県富山市" code="16201"/>	
     <codelabel label="石川県小松市" code="17203"/>	
     <codelabel label="石川県輪島市" code="17204"/>	
     <codelabel label="長野県松本市" code="20202"/>	
     <codelabel label="愛知県常滑市" code="23216"/>	
     <codelabel label="愛知県西春日井郡豊山町" code="23342"/>	
     <codelabel label="大阪府豊中市" code="27203"/>	
     <codelabel label="大阪府豊中市" code="27203"/>	
     <codelabel label="大阪府八尾市" code="27212"/>	
     <codelabel label="大阪府泉南郡田尻町" code="27362"/>	
     <codelabel label="兵庫県神戸市中央区" code="28110"/>	
     <codelabel label="兵庫県豊岡市" code="28209"/>	
     <codelabel label="和歌山県西牟婁郡白浜町" code="30401"/>	
     <codelabel label="鳥取県鳥取市" code="31201"/>	
     <codelabel label="鳥取県境港市" code="31204"/>	
     <codelabel label="島根県益田市" code="32204"/>	
     <codelabel label="島根県簸川郡斐川町" code="32401"/>	
     <codelabel label="岡山県岡山市" code="33201"/>	
     <codelabel label="岡山県岡山市" code="33201"/>	
     <codelabel label="広島県広島市西区" code="34104"/>	
     <codelabel label="広島県三原市" code="34204"/>	
     <codelabel label="山口県宇部市" code="35202"/>	
     <codelabel label="徳島県板野郡松茂町" code="36401"/>	
     <codelabel label="香川県高松市" code="37201"/>	
     <codelabel label="愛媛県松山市" code="38201"/>	
     <codelabel label="高知県南国市" code="39204"/>	
     <codelabel label="福岡県北九州市小倉南区" code="40107"/>	
     <codelabel label="福岡県福岡市博多区" code="40132"/>	
     <codelabel label="佐賀県佐賀郡川副町" code="41302"/>	
     <codelabel label="長崎県大村市" code="42205"/>	
     <codelabel label="長崎県対馬市" code="42209"/>	
     <codelabel label="長崎県壱岐市" code="42210"/>	
     <codelabel label="長崎県北松浦郡小値賀町" code="42383"/>	
     <codelabel label="熊本県上益城郡益城町" code="43443"/>	
     <codelabel label="宮崎県宮崎市" code="45201"/>	
     <codelabel label="鹿児島県枕崎市" code="46204"/>	
     <codelabel label="鹿児島県熊毛郡中種子町" code="46501"/>	
     <codelabel label="鹿児島県熊毛郡上屋久町" code="46503"/>	
     <codelabel label="鹿児島県大島郡喜界町" code="46529"/>	
     <codelabel label="鹿児島県大島郡天城町" code="46531"/>	
     <codelabel label="鹿児島県大島郡和泊町" code="46533"/>	
     <codelabel label="鹿児島県大島郡与論町" code="46535"/>	
     <codelabel label="沖縄県那覇市" code="47201"/>	
     <codelabel label="沖縄県石垣市" code="47207"/>	
     <codelabel label="沖縄県国頭郡伊江村" code="47315"/>	
     <codelabel label="沖縄県島尻郡座間味村" code="47354"/>	
     <codelabel label="沖縄県島尻郡粟国村" code="47355"/>	
     <codelabel label="沖縄県島尻郡南大東村" code="47357"/>	
     <codelabel label="沖縄県島尻郡北大東村" code="47358"/>	
     <codelabel label="沖縄県島尻郡久米島町" code="47361"/>	
     <codelabel label="沖縄県宮古郡多良間村" code="47375"/>	
     <codelabel label="沖縄県八重山郡竹富町" code="47381"/>	
     <codelabel label="沖縄県八重山郡与那国町" code="47382"/>	
 </ksjc:C002>	
</ksjc:CodeSet>	
End


# PrefCode.xml 都道府県コード
# 「国土数値情報(コードリスト)平成19年 国土交通省」
# http://nlftp.mlit.go.jp/ksj/jpgis/codelist/codelists.zip

$xml_pref =<<"End";
<?xml version="1.0" encoding="UTF-8"?>
<ksjc:CodeSet xmlns:ksjc="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app-cd" xmlns:jps="http://www.gsi.go.jp/GIS/jpgis/standardSchemas" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app-cd KsjCodelist.xsd">
 <ksjc:C001>
     <description>都道府県コード</description>
     <codelabel label="北海道" code="01"/>
     <codelabel label="青森県" code="02"/>
     <codelabel label="岩手県" code="03"/>
     <codelabel label="宮城県" code="04"/>
     <codelabel label="秋田県" code="05"/>
     <codelabel label="山形県" code="06"/>
     <codelabel label="福島県" code="07"/>
     <codelabel label="茨城県" code="08"/>
     <codelabel label="栃木県" code="09"/>
     <codelabel label="群馬県" code="10"/>
     <codelabel label="埼玉県" code="11"/>
     <codelabel label="千葉県" code="12"/>
     <codelabel label="東京都" code="13"/>
     <codelabel label="神奈川県" code="14"/>
     <codelabel label="新潟県" code="15"/>
     <codelabel label="富山県" code="16"/>
     <codelabel label="石川県" code="17"/>
     <codelabel label="福井県" code="18"/>
     <codelabel label="山梨県" code="19"/>
     <codelabel label="長野県" code="20"/>
     <codelabel label="岐阜県" code="21"/>
     <codelabel label="静岡県" code="22"/>
     <codelabel label="愛知県" code="23"/>
     <codelabel label="三重県" code="24"/>
     <codelabel label="滋賀県" code="25"/>
     <codelabel label="京都府" code="26"/>
     <codelabel label="大阪府" code="27"/>
     <codelabel label="兵庫県" code="28"/>
     <codelabel label="奈良県" code="29"/>
     <codelabel label="和歌山県" code="30"/>
     <codelabel label="鳥取県" code="31"/>
     <codelabel label="島根県" code="32"/>
     <codelabel label="岡山県" code="33"/>
     <codelabel label="広島県" code="34"/>
     <codelabel label="山口県" code="35"/>
     <codelabel label="徳島県" code="36"/>
     <codelabel label="香川県" code="37"/>
     <codelabel label="愛媛県" code="38"/>
     <codelabel label="高知県" code="39"/>
     <codelabel label="福岡県" code="40"/>
     <codelabel label="佐賀県" code="41"/>
     <codelabel label="長崎県" code="42"/>
     <codelabel label="熊本県" code="43"/>
     <codelabel label="大分県" code="44"/>
     <codelabel label="宮崎県" code="45"/>
     <codelabel label="鹿児島県" code="46"/>
     <codelabel label="沖縄県" code="47"/>
 </ksjc:C001>
</ksjc:CodeSet>
End

# run this script.

main();


# end of script

__END__



Headline text