2017-04-02

XML文書の更新 - 国土数値情報「行政区域」

XML文書から必要な情報を的確に抽出するには、何を、どの要素/属性で、どのような構造によって記述するかなどを定義した「応用スキーマ (Application Schema)」を参照する必要があります。通常、応用スキーマは 「○○仕様書」等の形態で文書化されており、また、XML文書の妥当性検証やデータ抽出等を自動化しやすいように、符号化規則をXML形式で記述した応用スキーマファイルが付属していることもあります。

応用スキーマは、特定の種類のデータセットをXML形式で記述する場合に従わなければならない仕様であり、あるXML文書についての応用スキーマが開示されなかったり、開示されたとしてもXML文書がその応用スキーマに適合していなかったりした場合には、一般にそのXML文書を正しく読むことはできません。

XML形式で提供するデータは、XMLの規格や応用スキーマに厳密に適合していなければなりませんが、その点でルーズであることにより、利用が難しいデータを見かけることもあります。

国土数値情報「行政区域」データにおけるXML要素名等は、応用スキーマ文書「国土数値情報(行政区域)製品仕様書 第 2.3 版」で定義されていますが、平成25年のデータにおける行政区域クラス、およびその属性を記述しているXML要素名はそれに適合していません(2017年4月2日にダウンロードした 平成25年 東京都 のデータで確認)。

クラス属性XML要素名 (製品仕様書2.3版)XML要素名 (平成25年データ)
行政区域AdministrativeBoundaryAdministrativeArea
範囲boundsare
都道府県名prefectureNameprn
支庁・振興局名subPrefectureNamesun
郡・政令都市名countyNamecon
市区町村名cityNamecn2
行政区域コードadministrativeAreaCodeaac

平成25年のデータ作成時の応用スキーマでは現在と異なる要素名が定義されていたのか、平成25年のデータが規格外なのか、あるいはその他の事情があるのか、理由は定かではありませんが、いずれにせよ、現在の製品仕様書に準拠して作成されたアプリケーションでこのデータを利用しようとするならば、XML要素名を変更する必要があります。

FMEでは、XML文書を処理するために多くのトランスフォーマーが用意されています。ここではそのひとつ、XMLUpdater トランスフォーマーを使い、国土数値情報「行政区域」の平成25年のデータ (XML文書) を、現在の製品仕様書に適合するように更新するワークスペース例を掲げます。

FME 2017.0.0.1 build 17271

FMEワークスペース例















[DATAFILE] リーダー: 国土数値情報「行政区域」データ (更新前XML文書) を読み込む
StringReplacer: 更新前XMLの誤記修正 (詳細は後述)
XMLUpdater: 行政区域の属性を記述しているXML要素名の変更
XMLFormatter: 更新後XMLの書式やエンコーディングの設定
[DATAFILE] ライター: 更新後XMLをファイルに出力

行政区域クラスXML要素の例
<!-- 更新前 -->
<ksj:AdministrativeArea gml:id="gy2">
    <ksj:are xlink:href="#sf2"/>
    <ksj:prn>東京都</ksj:prn>
    <ksj:sun></ksj:sun>
    <ksj:con>足立区</ksj:con>
    <ksj:cn2></ksj:cn2>
    <ksj:aac codeSpace="AdministrativeAreaCode.xml">13121</ksj:aac>
</ksj:AdministrativeArea>
<!-- 更新後 -->
<ksj:AdministrativeBoundary gml:id="gy2">
    <ksj:bounds xlink:href="#sf2"/>
    <ksj:prefectureName>東京都</ksj:prefectureName>
    <ksj:subPrefectureName/>
    <ksj:countyName>足立区</ksj:countyName>
    <ksj:cityName/>
    <ksj:administrativeAreaCode codeSpace="AdministrativeAreaCode.xml">13121</ksj:administrativeAreaCode>
</ ksj:AdministrativeBoundary>

[DATAFILE] リーダー/ライターによって、XMLを含む任意のフォーマットのファイルの読み書きができます。リーダーの Read Whole File at Once (ファイル全体を一度に読む) パラメーターを Yes に設定してファイルを読み込むと、そのファイルの内容 - この場合はXML文書の全体を格納した data_file_data 属性を持つフィーチャーが出力されます (1ファイルにつき1フィーチャー)。

このワークスペース例を作成している過程で、国土数値情報「行政区域」の平成25年のデータのルート要素に誤記があるのを見つけました。

<?xml version="1.0" encoding="UTF-8"?>
  <ksj:Dataset
  gml:id= "N03Dataset"
  xmlns:ksj="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app"
  xmlns:gml="http://www.opengis.net/gml/3.2"
  xmlns:xlink="http://www.w3.org/1999/xlink"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xmlns:schemaLocation="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app KsjAppSchema-N03-v2_0.xsd">

xmlns:<接頭辞>="<XML名前空間名>" は、文書内で使用するXML名前空間と、所属先の名前空間を識別するために要素名/属性名に付加する接頭辞を宣言する構文です。しかし、xmlns:schemaLocation="..." は、右辺の書式 "<URL><空白><応用スキーマファイル名>" から見て明らかにスキーマロケーションを示すことが意図されており、xsi:schemaLocation="..." とすべきところの誤記であると判断されます。

XMLの仕様に忠実なソフトウェアは、この誤記があることによってXML文書全体の読み込みを拒否することがあります。FMEがXML文書の更新等を行うために使用している XQuery プロセッサー (Zorba XQuery Processor) もこの誤記を許容しないので、まず、StringReplacer によって "xmlns:schemaLocation" を "xsi:schemaLocation" に置き換えました。

この修正を施したうえで XMLUpdater によって、行政区域の属性を記述するためのXML要素名を、現在の応用スキーマに準拠した名前に変更しました。

XMLUpdater には2つの入力ポート - Document と Update があり、更新したいXML文書を属性として持っているフィーチャーは Document ポートの方に入力します。

Update ポートから入力したフィーチャーの属性をXML更新用のパラメーター (Value) として使うこともできますが、この例では、その必要はありません。ただし、XMLUpdater を起動するには、少なくともひとつのフィーチャーを Update ポートに入力する必要があります。そのため、Creator を Update ポートを接続して、何も属性を持たないフィーチャーを1個だけ入力しています。

XMLUpdater パラメーター設定画面




























XMLUpdater で要素名を変更する場合は、パラメーター設定画面の Updates テーブルで、変更するノード (XML要素) ごとに次の事項を設定します。
  • Update Type: Rename (ノード名を変更) を選択
  • XML Path: 変更対象ノードのXML文書内での位置を示す XPath
  • Value Type: Plain Text (変更後のノード名を文字列で指定する場合)
  • Value: 変更後の文字列
このようにパラメーターを設定した XMLUpdater によってXML文書を更新することは、次のような XQuery 式を実行するのと同等です  (ワークスペースの実行時、FMEは XMLUpdater のパラメーター設定に基づいて XQuery 式を組み立てて実行します)。

declare namespace ksj="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app";
for $x in //ksj:AdministrativeArea return rename node $x as 'ksj:AdministrativeBoundary',
for $x in //ksj:are return rename node $x as 'ksj:bounds',
for $x in //ksj:prn return rename node $x as 'ksj:prefectureName',
for $x in //ksj:sun return rename node $x as 'ksj:subPrefectureName',
for $x in //ksj:con return rename node $x as 'ksj:countyName',
for $x in //ksj:cn2 return rename node $x as 'ksj:cityName',
for $x in //ksj:aac return rename node $x as 'ksj:administrativeAreaCode'

注1: この例では、[DATAFILE] リーダーでXML文書を読み込み、それを属性として持っているフィーチャーを XMLUpdater の Document ポートから入力しましたが、XMLUpdater の XML Input パラメーターで "XML File" を選択することにより、XML File パラメーターでファイル名を指定してXML文書を直接読み込ませる方法もあります。その方が効率が良さそうですが、国土数値情報「行政区域」平成25年のデータには前述の誤記があり、それを修正しないと XMLUpdater はXML文書を解析できなかったため、採用できませんでした。

注2: XMLUpdater トランスフォーマーではノード名の変更のほかに、ノードの置換、ノードの内容の置換、ノードの削除、ノードの内容の削除、ノードの挿入を行うことができます。

注3: XMLXQueryUpdater トランスフォーマーでは XQuery 式を直接指定し、それに基づくXML更新を行うことができます。XMLUpdater では対応できない複雑で高度なXML更新も、XMLXQueryUpdater を使えば可能になる場合があります (本記事末尾の [補足] 参照)。


次の XMLFormatter では、必要に応じて、インデント数、余分な空白の取り扱い、値を持たない要素の記述方法、エンコーディングなど、XML文書の書式全般を設定できます。この例では更新後XMLのエンコーディングを UTF-8 に設定しましたが、更新前XMLのエンコーディングも UTF-8 なので、必須ではありません。

ただし、[DATAFILE] ライターフィーチャータイプでは Character Encoding パラメーターを明示的に UTF-8 に設定する必要があります。

[DATAFILE] ライターフィーチャータイプ




























補足: XMLXQueryUpdater (やや高度な XQuery 式) の例

結果をチェックしていて、国土数値情報「行政区域」では、東京23区名が countyName (郡・政令都市名) 要素に記述されていることに気がつきました。平成25年に限らずどの年のデータでもそのようなので、仕様上は間違いないのだとは思いますが、一般的には、どちらかと言えば「市区町村名」の範疇で取り扱う方が多いような気がします。

仮に、countyName 要素に区名 "○○区" が記述されている場合、それを cityName 要素に記述し、countyName 要素からは削除することが必要になったとすれば、XMLXQueryUpdater によって次のような XQuery 式を実行すれば良さそうです。

declare namespace ksj="http://nlftp.mlit.go.jp/ksj/schemas/ksj-app";
for $x in //ksj:countyName[fn:ends-with(text(), '区')]
return (replace value of node $x/../ksj:cityName with $x/text(),
    replace value of node $x with '')

  • 末尾が「区」である文字列 (区名) を内容とする全ての ksj:countyName 要素について、
  • その sibling (兄弟姉妹) 関係にある ksj:cityName 要素の内容をその区名で置き換え、
  • ksj:countyName 要素の内容は空文字列 '' で置き換える (つまり、内容を削除する)。

0 件のコメント:

コメントを投稿