2017年5月17日水曜日

XMLファイル取り込み:地図情報

国土数値情報(http://nlftp.mlit.go.jp/ksj/index.html)の政策区域を取り込んでみる。例として医療圏を利用する。
内容を確認するため、静岡県をダウンロードして内容をチェックする。

1.構造の確認
ファイルの下の方にあるブロックから見ていく
これを見ると
FirstMedicalArea : 一次医療圏
administrativeAreaCode : 22101 地域コード(5桁)
cityName : 葵区
secondMedicalAreaCode : 2205 二次医療圏コード(4桁)
secondMedicalAreaName : 静岡  二次医療圏名
settingFlag : 2 一次医療圏を医療計画等で定義しているかどうかを判断するためのコードなのでいらない?(ほとんど2?)

これに対して「sf1」で検索すると「cv1_0」が範囲の情報に当たる。上にある緯度、経度のセットが境界情報
続いて二次医療圏のブロックを見る
SecondMedicalArea
これを見ると
AdministrativeAreaCode : 22207, 22210
CityName :  富士宮市、富士市
secondMedicalAreaCode : 2204
secondMedicalAreaName : 富士
areaOfRegionalMedicalPlan : 都道府県が定めた地域保健医療計画に掲載されている面積(㎡) : 634.01
areaOfGsi : 面積(国土地理院): 634.01
populationOfRegionalMedicalPlan : 人口(医療計画): 385752
totalPopulationOfBrr : 総人口(住民基本台帳): 394831
under15YearsOldPopulationOfBrr : 人口(15才未満)(住民基本台帳)55125
between15And64YearsOldPopulationOfBrr : 248263
over65YearsOldPopulationOfBrr : 91443

この「sf1114」で検索すると、領域情報がわかる
ThirdMedicalAreaに関しては、都道府県のはずなのでなぜ分かれているかわからないけど、あるので作っておく。
この「sf2192」で検索すると境界情報?があった
テーブル構成は次のようになる
都道府県テーブル(都道府県id, 名前)
2次医療圏テーブル(2次医療圏id(4桁),名前, 地域コード(5桁), 面積, 人口, 15歳未満人口, 15-64歳人口, 65歳以上人口)
2次医療圏境界テーブル(id, 2次医療圏id, latitude, longitude)
地域テーブル(地域コード(5桁), 名前)

テーブルを作成しbakeしておきます。
zonesテーブル(2次医療圏)にuploadアクションを追加します。この辺は前回と同じ。
続いてimportアクションの作成。前回より難しいのは2次医療圏のテーブルに情報を入れると同時に、境界情報をboundariesテーブルに入れないといけない。2次医療圏の情報挿入ループの中に、boundariesテーブルの挿入ループを書いていく。
public function import(){
APP::import('Model','Boundary');
$this->Boundary = new Boundary;
if($this->request->is('post')){
$up_file = $this->data['Zone']['XmlFile']['tmp_name'];
$fileName = 'post.xml';
if(is_uploaded_file($up_file)){
move_uploaded_file($up_file, $fileName);
$xmlArray = Xml::toArray(Xml::build($fileName));
foreach($xmlArray['Dataset']['ksj:SecondMedicalArea'] as $line){//2次医療圏の情報を入れる
$data = array(
'id' => $line['ksj:secondMedicalAreaCode'],
'population' => $line['ksj:totalPopulationOfBrr'],
'area' => $line['ksj:areaOfGsi'],
'population15' => $line['ksj:under15YearsOldPopulationOfBrr'],
'population1564' => $line['ksj:between15And64YearsOldPopulationOfBrr'],
'population65' => $line['ksj:over65YearsOldPopulationOfBrr']
);
$this->Zone->save($data);
$region_id = str_pad($line['ksj:secondMedicalAreaCode'],4,'0',STR_PAD_LEFT);//2次医療圏idは4桁
for($i = 0; $i < count($xmlArray['Dataset']['gml:Curve']);$i++){
$id = substr($xmlArray['Dataset']['gml:Curve'][$i]['@gml:id'],2);//cvXXXX_0なので最初のcvをとる
$id2 = explode("_",$id);//後ろの_0をとる
$link = substr($line['ksj:area']['@xlink:href'],3);//#sfXXXXで3文字目から
if($id2[0] == $link){
$latlng = explode(" ",$xmlArray['Dataset']['gml:Curve'][$i]['gml:segments']['gml:LineStringSegment']['gml:posList']);
for($j = 0; $j < count($latlng);$j+=7){
$data = array(
'region_id' => $region_id,
'latitude' => $latlng[$j],
'longitude' => $latlng[$j+1]
);
$this->Boundary->create($data);
$this->Boundary->save();
}
}
}
}
}
}
$this->redirect(array('action'=>'index'));
}
view raw import hosted with ❤ by GitHub

これでファイルをアップロードすると、無事に境界情報が入る(アップロードに10分位かかる)
あとは同じやり方で1次医療圏(地域)をやる。
 1次医療圏境界テーブル(id, 地域id(5桁), 緯度, 経度)

0 件のコメント:

コメントを投稿