2017-03-28

正規表現を利用したGML要素の変換

正規表現 (Regular Expression) は、文字列がある書式に従っているかどうかを判定したり、文字列から特定のパターンに一致する部分文字列を抽出したりするために使われる「パターンを表す文字列式」であり、多くのプログラム言語で、正規表現を使った一致判定、抽出、置換などの文字列処理機能が実装されています。

FMEのワークスペースでも、いくつかのトランスフォーマーで正規表現を使った文字列処理が可能であり、属性値の書式を検証したり修復したりするために効果的に使えることがあります。

ここでは、GML形式によってポイントジオメトリを記述しているXML断片 (fragment) について、座標 (緯度、経度) を記述している要素を FME が認識できる形式に変換するために正規表現を利用する例を紹介します。



処理の対象とするフィーチャーは loc という名前の属性を持っており、その値として次のXML断片 - GML形式で記述されたジオメトリ要素が格納されているものとします。

変換前のXML断片 (loc 属性の値)
<gml:Point gml:id="point96" srsName="epsg:4326">
    <gml:coordinates>31:56:00S 115:50:00E</gml:coordinates>
</gml:Point>

多くの場合、GeometryReplacer トランスフォーマーによってGML形式のXML断片に基づいてジオメトリを作成できますが、任意の書式による座標の記述が許容されている <gml:coordinates> 要素が使われている場合には、FMEが認識できる書式に変更するための前処理が必要になることがあります。

このXML断片における「<度>:<分>:<秒>S <度>:<分>:<秒>E」(S は南緯、E は東経であることを示す) も FME が認識できない書式です。

ここでは、元のXML断片における <gml:coordinates> 要素を、次のように <gml:pos> 要素に置き換えることとします。これであれば、GeometryReplacer によってジオメトリを作成することができます。

変換後のXML断片 (loc 属性の値)
<gml:Point gml:id="point96" srsName="epsg:4326">
    <gml:pos>-31.933333333333334 115.83333333333333</gml:pos>
</gml:Point>

注:  変換前のXML断片は、古いバージョンのGMLの仕様に関する参考資料に掲載されていたジオメトリ要素記述例からの引用です。現在のGMLの仕様では <gml:coordinates> 要素は非推奨 (deprecated) とされており、新しいデータで点の座標を記述する場合、通常は <gml:pos> 要素が使われます。GMLの仕様では、<gml:pos> 要素の値は実数のリスト (スペース区切り列挙) として記述することになっています。

FME 2017.0.0.1 build 17271

FME ワークスペース例







StringSearcher: <gml:coordinates> 要素、および座標値の各要素 (度、分、秒)を抽出
AttributeManager: 十進緯度 (_lat)、十進経度 (_lon)を求めるとともに、不要な属性を削除
StringReplacer: <gml:coordinates> 要素を <gml:pos> 要素に置換
GeometryReplacer: 変換後のXML断片 (loc 属性の値) に基づいてポイントジオメトリを作成

StringSearcher パラメーター設定例
















この設定でワークスペースを実行すると、Contains Regular Expression パラメーターに設定した次の正規表現がXML断片の中の部分文字列 "<gml:coordinates>...</gml:coordinates>" と一致し、その部分が _first_match 属性に格納されます。

<gml:coordinates>(\d+):(\d+):(\d+)S\s+(\d+):(\d+):(\d+)E</gml:coordinates>

また、正規表現の中の ( ) で囲んだ部分 (部分式) に一致する部分文字列 (この例の場合は緯度、経度それぞれの度、分、秒の値)が、元の文字列の先頭からの順番で _part{}.part リストに格納されます。

_part{0}.part: 南緯 度
_part{1}.part: 南緯 分
_part{2}.part: 南緯 秒
_part{3}.part: 東経 度
_part{4}.part: 東経 分
_part{5}.part: 東経 秒

次の AttributeManager では、このリストに格納された座標値の要素に基づいて、十進緯度 (南緯なので負)、十進経度を求め、それぞれ _lat, _lon という名前の属性に格納しました。また、必須のことではありませんが、この後の処理で不要な属性を削除しています。

AttributeManager パラメーター設定例












十進緯度、十進経度が求められたので、StringReplacer を使い、loc 属性値 (元のXML断片) について、<gml:coordinates> 要素と一致する部分 (_first_match 属性に格納されている) を <gml:pos> 要素 (値 = スペース区切りによる十進緯度、十進経度) と置き換えることができます。

StringReplacer パラメーター設定例























Attributes: 処理の対象とする文字列を格納している属性 (複数可)
Text To Replace: 置換前の部分文字列
Replacement Text: 置換後の部分文字列

置換前/後の部分文字列は、特定の文字列を直接入力することによって指定するほか、この例のように、属性値や文字列式によって指定することもできます。また、Mode パラメーターを Replace Regular Expression に設定すれば、Text To Replace パラメーター (置換前の部分文字列) を正規表現によって指定することもできます。

正規表現はプログラマーだけが使うものと思われるかも知れませんが、FMEユーザーならば、コーディングなしで正規表現を利用できます。正規表現を使うことによって、複雑で難しそうに見える文字列処理も簡単にできるケースは少なくありません。活用していただきたい技術のひとつです。

[2017-04-05 追記] 文字列置換を主題として考えていたのでうっかりしましたが、十進緯度、十進経度が求められたので、それらに基づいて VertexCreator によってポイントジオメトリを作成することもできます。ポイントの作成が最終目的である (GML断片を更新せずに破棄して良い) 場合は、VertexCreator を使った方が優れていると言えます。

0 件のコメント:

コメントを投稿