はじめに
上下水道業界で管路台帳システム(GIS)の運用に携わっている実務者です。
これまでの記事で半田市のオープンデータ(管路シェープファイル)を分析してきましたが、今回はその最初の一歩でつまずくポイント — 属性名が全部「SAFIELD000」問題 — を取り上げます。前半は「どう読み解くか」の実務ネタ、後半は「なぜこうなったのか(shapefile の 10 文字制約)」「この先どうなるのか(次世代標準 GeoPackage と国の動き)」という、形式の過去と未来の話です。
お断り: 本記事は公開データによる検証であり、対象自治体の実際の管渠の状態評価を示すものではありません。
「SAFIELD000」とは何か
半田市の管路シェープファイルを開くと、属性テーブルの列名が SAFIELD000〜SAFIELD045 という連番になっています。施工年度も管種も、どの列が何なのか一見分かりません。
これは台帳システム(WebGIS)からのエクスポート形式で、シェープファイル形式の古い制約(理由は次節)を避けるために、業務上の属性名を連番のフィールド名に退避させた形と考えられます(SAFIELD000 がちょうど 10 文字であることも、その推測を裏づけます)。そして大事なのは、変換の対応表がちゃんと同梱されていること。各レイヤの zip の中に、shp と同名の XML(S2AConfig 形式)が入っていて、そこに定義が書かれています。
<Field id="SAFIELD000">
<ColID>SEKOU_YEAR</ColID>
<DataType>S</DataType>
<Title>施工年度</Title>
</Field>
つまり「列名が分からない」のではなく「対応表を読めば分かる」設計です。手作業で照合してもいいのですが、レイヤ 34 個 × 最大 46 列。目視でやると確実に途中で嫌になる数なので、Python で自動化します。
なぜ連番の列名になるのか — 1980 年代生まれの 10 文字制約
そもそもなぜ、わざわざ意味の分からない連番に変換して出力するのでしょうか。不親切に見えて、実は理由のある設計です。
shapefile の属性テーブルの実体は .dbf ファイルで、これは 1980 年代の dBASE というデータベース形式そのものです(shapefile の仕様書 ESRI Shapefile Technical Description(1998) も、属性ファイルを「標準の DBF ファイル」と規定しています)。ファミコンとほぼ同世代の形式が、2026 年の台帳データ交換を今も支えているわけです。そして dBASE 形式のフィールド名には 最大 10 文字(バイト) という制約があります。
「施工年度」なら Shift_JIS で 8 バイトなので収まりますが(半田市のデータもこの文字コードです)、「上流土被り(m)」は収まりません。ちなみに同じ「施工年度」でも UTF-8 なら 12 バイトで、今度は収まらなくなります。さらに文字コードの罠もあります。.dbf の日本語の文字コードの解釈はソフトによってまちまちで、全角文字がバイト境界で切れると文字化けや読み込み失敗の原因になります。
台帳システムの側から見ると、任意の業務属性(日本語・長い・レイヤごとに構成が違う)を、どの GIS ソフトでも安全に開ける形で出力しなければなりません。その答えが「ASCII の連番フィールド名+定義は XML に外出し」です。表示名(施工年度)/ DB 列名(SEKOU_YEAR)/ 交換用列名(SAFIELD000)を分けて管理する三層構造は、業務システムでは定石的な設計でもあります(SA は Shape Attribute の略と推測します)。
つまり SAFIELD は、40 年以上前に生まれた dBASE 形式の制約に対する堅実な回避策です。
なお、この制約自体から卒業する動きも始まっています — その話は最後の章に取っておいて、まずは目の前の SAFIELD を読み解きます。
XML をパースして属性辞書を作る
標準ライブラリの xml.etree.ElementTree だけで書けます。
import xml.etree.ElementTree as ET
from pathlib import Path
def parse_layer_xml(path: Path) -> list[dict]:
root = ET.parse(path).getroot()
layer_no = root.findtext(".//LayerNo") or path.stem
rows = []
for field in root.findall(".//ShapeAttributeConfig/Fields/Field"):
title = field.findtext("Title") or ""
col_id = field.findtext("ColID") or ""
if not title and not col_id:
continue # 業務的な意味を持たないシステム列はスキップ
rows.append({
"layer_no": layer_no,
"field_id": field.get("id", ""),
"col_id": col_id,
"title": title,
})
return rows
rows = []
for xml_path in sorted(Path("data").glob("*/*/*.xml")):
if xml_path.stem != xml_path.parent.name:
continue # Thematicmap.xml などレイヤ定義以外を除外
rows.extend(parse_layer_xml(xml_path))
ポイントは 2 つだけです。
- レイヤ定義の XML はレイヤフォルダ名と同名(
24021/24021.xmlなど)。同じフォルダのThematicmap.xmlはレイヤ定義ではないので、ファイル名で除外します。 -
Titleが日本語の属性名、ColIDが元システムでの列名です。両方保存しておくと後で照合に便利です。
これで全レイヤの対応表(CSV)が数秒で生成でき、あとは geopandas で読んだデータフレームを rename するだけです。
復元してみると、台帳の中身は立派
対応表を当てて分かったのは、このエクスポートが業務台帳としてかなり充実していることです。例えば:
| レイヤ | 属性数 | 中身の例 |
|---|---|---|
| 下水道・管渠 | 5 | 施工年度・管種名称・管径・上流/下流土被り |
| 下水道・マンホール | 22 | 人孔キー・処理分区・人孔深・地盤高・舗装種別・資産番号 など |
| 上水道・弁栓 | 46 | 弁種類・口径・開閉状態・実測圧・修繕経歴×5 回分・固定資産番号 など |
列名が連番だからといって中身が貧弱なわけではまったくなく、むしろ「読み解けば宝」でした。過去 2 記事の劣化リスク分析は、この属性辞書の復元が出発点になっています。
実務でどう使えるか
- 自治体オープンデータの利用者: この形式のエクスポートは半田市固有とは限らず、筆者が見た範囲では同系の台帳システムを使う自治体で見かけます。「SAFIELD で諦めない」だけで使えるデータが増えます。
- 台帳データの受け渡し・検収: システム更新やデータ移行で他社形式のエクスポートを受け取るとき、属性辞書を自動生成して突合すれば、属性の欠落・取り違えを機械的に検査できます。令和 9 年度以降、改築で交付金の対象となる管路施設は、施設情報や維持管理情報を「地理情報システムを基盤としたデータベースシステム」で管理していることが要件化される(国交省「下水道事業における事業マネジメント実施に関するガイドライン -2024 年版-」p.14 表 2-4 脚注 2)流れの中で、この種のデータ受け渡しは確実に増えます。
- データ公開する自治体側: 対応表 XML を同梱する設計はとても親切です。公開時にデータリスト(Excel 等)へ属性一覧を転記しておくと、利用者はさらに助かります。
次世代の標準「GeoPackage」— この制約、いつまで付き合う?
ここまでは「shapefile の制約とうまく付き合う方法」の話でした。最後に、そもそも制約のない後継形式の話をします。
shapefile の弱点は 10 文字制約だけではありません。業界の有志が「Shapefile must die!(shapefile は滅ぶべし)」という物騒なタイトルのサイトで制約を列挙しているほどです(タイトルに反して、中身は冷静な技術文書です)。主なものだけでも:
| 弱点 | 実務で困る場面 |
|---|---|
| 列名は最大 10 文字(バイト) | 本記事の主役。日本語だと Shift_JIS で全角 5 文字、UTF-8 なら 3 文字で頭打ち。文字コード変換時に属性名が切り捨てられる原因にもなる |
| 文字コードを宣言する方法が仕様にない | 1998 年の仕様書に .cpg の記載はなく、後付けの慣習。日本語データでは文字化けの温床になる |
| 最低 3 ファイル構成(.shp/.shx/.dbf) | 座標系の .prj は 1998 年の仕様書に登場すらしない「仕様外のオマケ」で、欠落しがち |
| 文字属性は 254 文字(バイト)まで | 長い備考・修繕履歴が入りきらない。日本語は Shift_JIS で 127 文字・UTF-8 で 84 文字が上限で、変換時に属性値が切り捨てられることもある |
| NULL がない・日付型に時刻がない | 数値の「0」と「未入力」が区別できない(Esri のドキュメント) |
| 各ファイル 2GB 上限 | 大規模データで頭打ち |
実は第 1 回で .prj が空っぽのせいで座標系を推定するハメになったのも、この「.prj は仕様外」問題そのものでした。
これらを解決する後継として、OGC(Open Geospatial Consortium — 地理空間情報の国際標準化団体)が定めたオープン標準が GeoPackage(拡張子 .gpkg)です(仕様の改訂履歴によれば 1.0.0 は 2014 年)。実体は SQLite(1 ファイルで完結する軽量データベース。スマホアプリの内部などで広く使われています)のファイル 1 個で、
-
列名の 10 文字制約がない。
SEKOU_YEARのような列名をそのまま持てるので、SAFIELD 方式の退避がそもそも要りません(仕様上は日本語列名も可能ですが、ツール間の互換性のため小文字英数字+アンダースコアが推奨されています)。 - 文字コードは Unicode(UTF-8/UTF-16)に限定。Shift_JIS 混在による文字化けが構造的に起きません。
- 座標系情報はファイル内に必須で格納(仕様の gpkg_spatial_ref_sys テーブル)。別ファイル(.prj)が付いてこない・空だった、という事故は構造的に起きません(座標系を「未定義」として記録することは仕様上可能ですが、それは別の話です)。
- 1 ファイルに複数レイヤを格納できます。半田市の 34 レイヤも理屈の上では 1 ファイルにまとまります。
- 254 文字上限・NULL 非対応・2GB 上限もありません。
対応状況も「これから」ではなく「とっくに」で、QGIS はベクタデータのデフォルト形式が GeoPackage ですし、geopandas でも 1 行です。
gdf.to_file("handa_sewer.gpkg", layer="pipes") # 書き出し(拡張子から自動判別)
gdf = gpd.read_file("handa_sewer.gpkg", layer="pipes") # 読み込み
そして国も動き始めています。国総研が能登半島地震の教訓を踏まえて公開した「地震対応における下水道管路データ交換標準仕様書(素案)」(令和 8 年 3 月)は、被災自治体と支援自治体の間で管路台帳データをやり取りする際のファイル形式を OGC GeoPackage(.gpkg、文字コード UTF-8) と規定しました(仕様書 p.70「配布書式情報」)。「災害時のデータ交換」という限定された用途の、しかも素案段階ではありますが、国の機関が管路台帳の受け渡し形式に GeoPackage を指定した公文書が出たことになります。
とはいえ、全国の台帳システムやオープンデータが一斉に置き換わるわけではありません。shapefile は「どのソフトでも確実に開ける」という一点で今なお交換形式の事実上の標準であり、SAFIELD 形式のエクスポートも当分残るはずです。だからこの記事の読み解き術は、移行が完了するまでの生存術です。
10 年後、この記事が「shapefile 時代は列名をこうやって復元していたらしい」という古文書として発掘される日が来たら、それはデータ環境が良くなった証拠です。その日が来るのを、書いた本人としては楽しみにしています。
まとめ
- 「SAFIELD000」は行き止まりではなく、同梱の S2AConfig 形式 XML に対応表があります。
- 連番列名の正体は、shapefile(dBASE)の 10 文字制約と文字コード問題への堅実な回避策です。形式の歴史を知ると、設計の意図が読めるようになります。
- 後継標準の GeoPackage には 10 文字制約も文字化けも .prj 欠落もなく、QGIS のデフォルト形式として既に実用段階です。国総研の災害時データ交換標準(素案)も GeoPackage を採用しており、移行の方向は見えています。
- 標準ライブラリの XML パースだけで、全レイヤの属性辞書を数秒で自動生成できます。
- 復元してみると台帳の中身は充実しており、分析の出発点になります。列名で諦めるのはもったいない。
関連記事: 上下水道×データの記事は一覧からどうぞ。コードは GitHub で公開しています。
免責・出典
- 本記事は手法のデモであり、半田市の実際の管渠の状態評価ではありません。
- 出典: 半田市「水道管路等データ」(CC BY 4.0)を加工して作成(図表の値は例示)
- 「Shapefile must die!」のサイトは http のみで公開されています(https では証明書のホスト名が一致せず開けません)。
