地図XMLをダウンロードして座標系をWindows PowerShellで調べる（コマンド）

これは自分のためのメモですが、このページをご覧になるかたは、登記所備付地図、いわゆる地図XMLについて、
* 全国でいくつの地図XMLファイルがありますか？
* 任意座標系のファイルはどのくらいありますか？各ファイルの座標系の一覧は？

なんていう疑問を持っているのではないでしょうか。ここではそんな素朴な疑問への回答を探すための方策をメモします。

# はじめに
法務省登記所備付地図（地図XML）は、法務省が２０２３年１月にG空間情報センターを介して公開しました。その後２０２３年８月末には更新がされています。

G空間情報センターからは、全国の地番地図のデータが提供されていますが、一方で多くのファイルが任意座標上で管理されており、公共座標系のデータとの整合やGISソフトでの位置合わせが難しいというようなところもあります。

全国の地番地図を扱いたいときに、どの町字、地番区域のデータが任意座標なのかを知ることは、位置合わせのための作業量を見積もるために重要です。よく参照されるが全国で地籍調査が終わったところの割合ですが、それはそのまま地図XMLの割合なのかはわかりません。私は、そもそも地図XML全体のなかでどのくらいのファイルが任意座標なのか整理したいと思い、実験を行いました。



# 前提条件など
## 私の環境
* Windows 11 home
* Windows PowerShell version 5.1.22621.2506

## 地図XMLの構造
地図XMLの構造というかファイルの構成ですが、簡単にいうと：
* 市区町村ごとにZIPダウンロード
* 各市区町村パッケージにリストとXMLファイル（ZIP）が格納
* （各XMLの構造、スキーマは仕様書に書いてある）
となります。詳しく説明します。

（段階１：市区町村ごとのパッケージ）
地図XMLはG空間情報センターからダウンロードするときに、年度別ですが、「市区町村-法務局」のグループでダウンロードできます。複数ファイルがまとまったパッケージでダウンロードできますが、「市区町村コード（５桁）-法務局コード（４桁）-年度（４桁）.zip」というファイル名でダウンロードができます。

 * 注意１：　政令指定都市は「区」の単位でダウンロードとなります。
 * 注意２：　同じ市区町村でも複数の法務局がデータを提供しているケースがあります（新潟市北区、岡山県北区など）。このようなところではすべてのデータをそろえたいときには複数のパッケージをダウンロードする必要があります。
 * 注意３：　市町村未定の東京都鳥島は、どのパッケージに含まれるのか見つけられませんでした。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/0b107440-2d0b-12a9-9e97-bc06a7081a9d.png)

（段階２：リストと個別のXML）
ダウンロードしてきた「市区町村ー法務局ー年度」のＺＩＰファイルの中には、地番と対応するＸＭＬを整理したリスト（ＣＳＶ）と、個別のＸＭＬファイル（ＺＩＰ）が入っています。リストはCSV形式ですが、XMLファイルはZIPファイルとしてあるので、利用するときは解凍が必要です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/ca23fb8e-a277-9555-34cf-ae76b47777d3.png)

リストには、各地番に対するファイル名とその出力年月日・時刻が格納されています。各地番に対するファイル名なので１カラム目のファイル名では複数回出てくるファイルもあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/5f32f9ed-6a06-5e5a-a850-0f7a1ab5cb49.png)

複数の地番の筆界未定地はまとめて一つのポリゴンになっているわけですが、リストの中では地番カラムが「筆界未定地-n」として書かれており、続くカラムに含まれる地番が入っています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/ae6962b1-0e17-e9a4-de64-039e1d23baba.png)

という感じが地図XMLファイルの構造ですが、二段階のＺＩＰファイルがあるのことは少し独特かなと思います。




# 手順
## Step1: 2023年の地図XMLのダウンロード
以前の記事に書きましたが、G空間情報センターのAPIを活用して、地図XMLファイルをダウンロードします。2023年のものをダウンロードしましたが、PCのスリープモードを切るのを忘れていたこともあり丸一日くらいかかりました。
```powershell:PowerShellで実行
$jsonData = (curl.exe 'https://www.geospatial.jp/ckan/api/3/action/resource_search?query=name:-2023.zip&limit=2005' | ConvertFrom-JSON)

for ($i=0; $i -lt $jsonData.result.results.name.length ; $i++ ){
  curl.exe -LO $jsonData.result.results.URL[$i]
}
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/22b7ac0f-b71c-f0fe-d7d7-67434a1ffb6f.png)

合計2,005ファイルをダウンロードしました。合計サイズは94.5 GB でした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/8e87b2e9-2d4b-309d-4a44-8a74ec5efe34.png)

400MBを超えるファイルは7つでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/58a97fb9-f773-3773-12ed-ffe65b2bc505.png)



## Step２: 地図XMLの投影法チェック　（時間がかかりすぎ失敗）
以下のような流れで各XMLファイルの投影法をチェックしていきます。
基本的なフローは以下の通りにしようと考えました。

1. ダウンロードした市区町村パッケージの1つを作業フォルダに解凍
1. その中のリストを別のところにコピーします。（将来、地番とファイルの関係を使って、地番と投影法の関係を出したいので。）
1. XMLファイルはZIPになっているので、それをもう一度解凍し、XMLに書いてある投影法を出力します。XMLファイル名、サイズ、投影法を出力するようにします（XMLの読み込みはWindowsPowerShellの機能を使いますが、処理を見ているとここで結構時間を使っているようです。）
1. 作業フォルダの中を削除して、ここまでのループを繰り返します。

以下のようなスクリプトを作成しましたので、前の工程でダウンロードしたディレクトリに移動して、PowerShellにコピペします。
```powershell
# 作業フォルダの準備
#rm unpack
#rm list
mkdir unpack
mkdir list

# 出力ファイル名を定義
$result = "xml-projection-list.csv"

# 出力ファイルを初期化
if(Test-Path $result){
  rm $result
}

# XMLの市区町村パッケージ（ZIP）リストの取得
$zipList = Get-Childitem -Path . -filter *.zip

##################
# 各市区町村ごとのループ開始
foreach($zippedPack in $zipList){

  # 市区町村のパッケージfileをunpackフォルダに解凍
  Expand-Archive $zippedPack -DestinationPath unpack
  # unpackフォルダ中のZIPファイルをリスト
  $testList = Get-Childitem -Path unpack -filter *.zip
  # unpackフォルダ内のzipファイルを解凍
  foreach($item in $testList){
    Expand-Archive unpack/$item -DestinationPath unpack 
    Write-host($item)
  }

  # 解凍したlistを移動
  $moveFile = $zippedPack -replace "-2023.zip", ".csv"
  Move-Item unpack/*.csv -Destination list

  # unpackフォルダ内のzipファイルを削除
  rm unpack/*.zip

  # unpack フォルダ内のxmlファイル一覧を取得
  $xmlList = Get-Childitem -Path unpack -filter *.xml

  ##################
  #各XMLファイルについて処理
  foreach($xmlFile in $xmlList){
    cd unpack

    # 初期化 
    if ($chizuXml) {
      remove-variable chizuXml
    }
    if ($chizuContent) {
      remove-variable chizuContent
    }

    # XMLファイルから投影法の取得
    $chizuContent = Get-Content($xmlFile) -Encoding UTF8 #なぜかUTF8
    $chizuXML = [xml]$chizuContent

    # 出力ファイルに書き出し
    cd ..
    Write-Output "$xmlFile, $($xmlFile.Length), $($chizuXML.地図.座標系)" | Add-Content $result

  }
  rm unpack/*
}
```

PowerShellにコピペすると動きます。2,005の市区町村がそれなりの数の地図XMLファイルを持っているので、仮に1市区町村が100くらいだとして20万件のXMLを読み込まないといけません。かなり時間がかかりそうなので、作業マシンがあれば複数のマシンにデータを分けて処理させたほうが良いかもしれませんね。

メモリも結構使っています↓。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/83614d3f-7a31-8386-15ce-2617770d1d19.png)

→ 作業自体は狙った通り進みますが、XMLを構造化して変数に読み込むのに時間がかかるのか、なかなか進みません。8時間くらい作業したところで、全部で10日くらいかかると思ったので方針を変えます。


## Step２（再度）: 地図XMLの投影法チェック

地図ＸＭＬの投影法について、ＸＭＬの構造で抜き出すのではなく、テキスト検索で抜き出すことにしました。（Select-String）
したがって、スクリプトを以下のように修正します。

```powershell
# 作業フォルダの準備
#rm unpack
#rm list
mkdir unpack
mkdir list

# 出力ファイル名を定義
$resultTXT = "projection-list.txt"
$fileSize = "xml-file-size.txt"

# 出力ファイルを初期化
if(Test-Path $resultTXT){
  rm $resultTXT
}
if(Test-Path $fileSize){
  rm $fileSize
}


# XMLの市区町村パッケージ（ZIP）リストの取得
$zipList = Get-Childitem -Path . -filter *.zip

##################
# 各市区町村ごとのループ開始
foreach($zippedPack in $zipList){

  # 市区町村のパッケージfileをunpackフォルダに解凍
  Expand-Archive $zippedPack -DestinationPath unpack
  # unpackフォルダ中のZIPファイルをリスト
  $testList = Get-Childitem -Path unpack -filter *.zip
  # unpackフォルダ内のzipファイルを解凍
  foreach($item in $testList){
    Expand-Archive unpack/$item -DestinationPath unpack 
    Write-host($item)
  }

  # 解凍したlistを移動
  Move-Item unpack/*.csv -Destination list

  # unpackフォルダ内のzipファイルを削除
  rm unpack/*.zip

  # unpack フォルダ内のxmlファイルの座標系を検索。ファイル一覧も記録。
 
  if ($zahyo) {
    remove-variable zahyo
  }
  $zahyo = Select-String "座標系" unpack/*.xml
  Write-Output $zahyo | Add-Content $resultTXT
  #Get-Item unpack/* | Add-Content $fileSize #ファイル名しか記録されない
  Get-Item unpack/* >> $fileSize #ファイルサイズも残る

  # unpackフォルダをクリーン
  rm unpack/*
}

```

これでも実行するのに2日近くかかりました。いくつかのグループに分けて並行して処理したほうが良かったかもしれません。
なお、5ファイルほどダウンロードが不完全だったようで、できたファイルが2,000だったので、残り５ファイルは改めてダウンロードして実行しました。


こんな感じでリストができる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/c9ee2483-2b07-9cf5-4f18-724ae890fbf9.png)
* projection-list.txt： xmlファイルとその投影法（座標系）
* xml-file-size：　zipを解凍したときにlsコマンドを実行して各ファイルのサイズをメモ
* listのフォルダ：　zipファイルを解凍したときに入っている{市区町村コード}-{法務局コード}-search-list.csv を移動してきています。一つのzipファイルに一つなので全部で2,005です。各地番の含まれるファイルを示すので行数は相当になります。

なお、リストで座標系はSelect-Stringにしたので、地図名に「座標系」を含むファイルを３つ拾っていました。それらを削除します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/bea1b071-a12b-2fde-6eb4-9dc87b4c8ee0.png)

こうしてできたリスト↓
https://raw.githubusercontent.com/ubukawa/chizu-xml1/main/xml-projection-list.txt



# 結果
すべてのXMLファイルについて投影法（座標系）のリストができました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/f9bc9d91-1698-846e-eed0-8b9b71ec7592.png)

＜いえること＞
* 2023年度の地図XMLは全部で315,034ファイルがあります。（市区町村-法務局　別には2,005のzIPファイル）
* XMLファイル数ベースでは各座標系の割合は以下の通りでした。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/679143/33c78e33-cc61-2ba3-ab6f-f15d6540c3ae.png)


# まとめ
地図XMLについて少し深く調べました。ファイル数ベースでは任意座標が57%と分かりました。
地図XMLファイルの投影法一覧も得られました。今後、例えば市区町村ごとにファイル数ベースですが、任意座標系の割合を出すこともできます。

別途、地番のリストも得ることができました。ファイルサイズが大きいですが、うまく使えば地番ごとの投影法のリストも作ることができるはずです。

# 参考ページ
https://front.geospatial.jp/moj-chizu-xml-download/

https://qiita.com/T-ubu/items/466ee9fcaad8345e1c77