2015-07-30

XMLの読込 - 断片化と平坦化

XMLはプラットフォームに依存しない汎用的なデータ交換用フォーマットとしてさまざまな分野で利用されています。

FMEでは、Fragmentation (断片化) と Flattening (平坦化) という2つの手法によって任意のXML文書からデータを抽出、変換することができます。

FME 2015.1.1.0 build 15515

=====
基盤地図情報「基本項目」等高線, 標高点データを Shapefile 形式に変換する。

ソースデータ:
基盤地図情報ダウンロードサービスサイトからダウンロードした「基本項目」等高線, 標高点データ (GML形式)
ダウンロードファイル名:
等高線: FG-GML-aaaaaa-Cntr-bbbbbbbb-cccc.xml
標高点: FG-GML-aaaaaa-ElevPt-bbbbbbbb-cccc.xml
aaaaaa は2次メッシュコード, bbbbbbbb は年月日, cccc は枝番
=====

FMEワークスペース例























[XML] リーダー: 基盤地図情報「基本項目」等高線、標高点データを読み込む。
GeometryReplacer: ジオメトリを記述しているXML文書の断片 (GML形式) に基づきジオメトリを作成する。
[SHAPE] ライター: Shapefile 形式のファイルに出力する。

注: 基盤地図情報の応用スキーマは FME に組み込まれており、基本項目は [GML] リーダーで読み込むことができますが、このワークスペース例では、断片化、平坦化の仕組みを示すために汎用の [XML] リーダーを使いました。

結果: FME Data Inspector による表示


















次の簡単なXML文書を例として、Fragmentation (断片化) と Flattening (平坦化) について説明します。

<?xml version="1.0"?>
<dataset>
  <Feature id="1">
    <name>abc</name>
    <position>
      <x>139.878794000</x>
      <y>35.764632528</y>
    </position>
  </Feature>
  <Feature id="2">
    <name>xyz</name>
    <position>
      <x>139.875861750</x>
      <y>35.759115861</y>
    </position>
  </Feature>
</dataset>

Fragmentation (断片化): 特定の名前のXML要素を抽出し、それをルート要素とするXML文書を作成する。

上記例を Feature 要素について断片化すると、次の2つのXML文書が作成されます。断片化によって作成された個別のXML文書を fragment (断片) と呼びます。

<?xml version="1.0"?>
<Feature id="1">
  <name>abc</name>
  <position>
    <x>139.878794000</x>
    <y>35.764632528</y>
  </position>
</Feature>

<?xml version="1.0"?>
<Feature id="2">
  <name>xyz</name>
  <position>
    <x>139.875861750</x>
    <y>35.759115861</y>
  </position>
</Feature>

Flattening (平坦化): XML要素・属性の値を抽出し、元の要素・属性名で構成される名前の属性に格納する。

平坦化後の属性名は、XMLドキュメントツリーにおける上位から下位の順で、XML要素名・属性名をドット "." 区切りで連結した文字列となります。上記例を Feature 要素について断片化した後、さらに平坦化すると次のようなテーブルが得られます。








[XML] リーダーの基本的な機能は、パラメーターで指定された要素についてXML文書を断片化し、個々の断片をフィーチャーとして読み込むことです。さらにオプションとして、断片化した要素の平坦化や、断片内の下位のXML要素の断片化ができます。

ワークスペース例では、リーダーをワークスペースに追加する際、Add Reader 画面 Format フィールドで XML を選択した後、次のようにパラメーターを設定しました。

[XML] リーダーパラメーター設定画面























Configuration Type: Feature Paths (デフォルト)
[XML] リーダーの構成方法として他に xfMap, XRS ファイルによる方法もありますが、Feature Paths が推奨されています。

Elements to Match:
断片化するXML要素名を指定します。複数あるときはスペースまたは改行区切りで列挙します。
この例では、個々の等高線、標高点のデータが記述されているXML要素名 (等高線: Cntr, 標高点: ElevPt) を指定しました。

Flatten Options: Options ボタンクリック => XML Flatten Options 画面 (右上)
断片化したXML要素を平坦化する場合に Enable Flattening チェックボックスをチェックします。
=====
注: FME 2016 以降では、デフォルトで Enable Flattening チェックボックスがチェックされています。
=====

Descendant Options: Options ボタンクリック => XML Descendant Options 画面 (右下)
Elements to Match で指定したXML要素の下位のXML要素も断片化する場合に、そのXML要素名を指定します。複数あるときはスペースまたは改行区切りで列挙します。

この例では、GML形式でジオメトリが記述されているXML要素 (等高線: Curve, 標高点: Point) を断片化し、後述するように、それらに基づいて GeometryReplacer によってジオメトリを作成することとしました。

注: この例のように Elements to Match パラメーターで指定したXML要素 (Cntr, ElevPt) の下位にGML要素 (Curve, Point) がある場合は、上位の断片 (後述の "xml_fragment") に基づいて GeometryReplacer によってジオメトリを作成することもできますが、ここでは Descendant Options の働きを示すために Curve, Point 要素を断片化しました。

以上の設定をした後、Add Reader 画面 Dataset フィールドで基盤地図情報「基本項目」等高線、標高点データファイルを選択してリーダーを追加すると、キャンバスには Elements to Match で指定したXML要素名と同じ名前のフィーチャータイプが現れます。

XML リーダーフィーチャータイプ (左: 等高線, 右: 標高点)


















平坦化オプションを指定したので、これらのフィーチャータイプの属性リストには下位のXML要素・属性に対応する属性が追加されました (Cntr.id, alti, など)。

"xml_fragment" 属性には、断片化されたXML文書 (Cntr, ElevPt をルート要素とする) が格納されます。

Descendant Options によって抽出される下位のXML要素の断片は "xml_fragment_<XML要素名>{}" という名前のリスト属性に格納されます。この例では次のとおりです。

等高線: xml_fragment_Curve{}
標高点: xml_fragment_Point{}

スキーマによっては同じ名前の下位XML要素が複数あることもあるので、下位の断片はそれらを要素とするリスト属性として抽出されます。この例ではリストの要素数は常に1です (各フィーチャーはジオメトリ要素をひとつずつ持つ)。

次に基盤地図情報「基本項目」等高線、標高点XML文書を抜粋して掲載します。[XML] リーダーによる断片化、平坦化の結果 (キャンバス上のフィーチャータイプ及びその属性リスト) と見比べて下さい。

青色の部分は Descendant Options の設定によって断片化される下位要素 (GML形式でジオメトリが記述されている部分) です。
----------
(基盤地図情報 等高線XML)
<?xml version="1.0" encoding="utf-8"?>
<Dataset xsi:schemaLocation="http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema FGD_GMLSchema.xsd"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema"
gml:id="Dataset1">
  <gml:description>基盤地図情報メタデータ ID=fmdid:14-1001</gml:description>
  <gml:name>基盤地図情報ダウンロードデータ(GML版)</gml:name>
  <Cntr gml:id="K3_5035512870_1">
    <fid>50355-12870-s-12800</fid>
    <lfSpanFr gml:id="K3_5035512870_1-1">
      <gml:timePosition>2014-09-01</gml:timePosition>
    </lfSpanFr>
    <devDate gml:id="K3_5035512870_1-2">
      <gml:timePosition>2014-10-16</gml:timePosition>
    </devDate>
    <orgGILvl>25000</orgGILvl>
    <loc>
      <gml:Curve gml:id="K3_5035512870_1-g" srsName="fguuid:jgd2011.bl">
        <gml:segments>
          <gml:LineStringSegment>
            <gml:posList>
35.752999472 139.875000000
35.752998472 139.875004472
(中略)
35.750000000 139.878976306
            </gml:posList>
          </gml:LineStringSegment>
        </gml:segments>
      </gml:Curve>
    </loc>
    <type>一般等高線</type>
    <alti>2.5</alti>
  </Cntr>
  (以下 Cntr 要素の繰り返し)
</Dataset>
----------
(基盤地図情報 標高点XML)
<?xml version="1.0" encoding="utf-8"?>
<Dataset xsi:schemaLocation="http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema FGD_GMLSchema.xsd"
xmlns:gml="http://www.opengis.net/gml/3.2"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns="http://fgd.gsi.go.jp/spec/2008/FGD_GMLSchema"
gml:id="Dataset1">
  <gml:description>基盤地図情報メタデータ ID=fmdid:14-1001</gml:description>
  <gml:name>基盤地図情報ダウンロードデータ(GML版)</gml:name>
  <ElevPt gml:id="K2_5035512873_1">
    <fid>50355-12873-i-9</fid>
    <lfSpanFr gml:id="K2_5035512873_1-1">
      <gml:timePosition>2013-08-14</gml:timePosition>
    </lfSpanFr>
    <devDate gml:id="K2_5035512873_1-2">
      <gml:timePosition>2014-10-16</gml:timePosition>
    </devDate>
    <orgGILvl>25000</orgGILvl>
    <vis>表示</vis>
    <pos>
      <gml:Point gml:id="K2_5035512873_1-g" srsName="fguuid:jgd2011.bl">
        <gml:pos>35.764632528 139.878794000</gml:pos>
      </gml:Point>
    </pos>
    <type>標高点(測点)</type>
    <alti>3</alti>
  </ElevPt>
  (以下 ElevPt 要素の繰り返し)
</Dataset>
----------

Descendant Options によって断片化した下位XML要素 (等高線: Curve, 標高点: Point) はGML形式なので、それに基づいて GeometryReplacer によってジオメトリを作成することができます。

GeometryReplacer パラメーター設定画面 (左: 等高線, 右: 標高点)












Fragmentation (断片化)、Flattening (平坦化) は XMLFragmenter, XMLFlattener トランスフォーマーによってデータフローの途中で行うこともできます。

XMLは汎用フォーマットであり、用途に応じて具体的なデータ構造 (スキーマ) が異なりますが、どのようなスキーマであってもこれらの仕組みを使うことにより、データを抽出、変換するためのワークスペースを作成することができます。

補足:
[XML] リーダーで平坦化をすると、デフォルトではフィーチャータイプとしたXML要素の全ての下位XML要素・属性がフィーチャー属性として抽出されますが、必要がない属性も多数含まれることがあります。

データフローのどこでも AttributeRemover/AttributeKeeper によって不要な属性は削除できますが、[XML] リーダーの Flatten Options では、初めから属性として抽出しない (無視する) 下位XML要素を指定することもできます。

Flatten Options の設定は、リーダーをワークスペースに追加した後でも、Navigator ウィンドウからパラメーター設定画面を開いて行うことができます。


















XML Flatten Options 画面で Ignore Specific Sub-Elements (特定の下位要素を無視する) チェックボックスをチェックしたうえで、Sub-Elements To Ignore (無視する下位要素) フィールドに、フィーチャー属性として抽出しない下位XML要素名を列挙します。
-----
devDate fid lfSpanFr loc orgGILvl pos vis
-----
パラメーター設定画面をOKで閉じれば、これらのXML要素 (その下位要素を含む) はフィーチャー属性として抽出されなくなります。

ただし、パラメーターの設定を変更しただけでは、キャンバス画面上のリーダーフィーチャータイプは更新されず、その属性リストには抽出されない属性名も表示されたままです。

Workbench メニュー: Readers > Update Feature Types によって、パラメーターの設定内容を画面上のリーダーフィーチャータイプのインターフェースにも反映させることができます。

FMEワークスペース例: リーダーフィーチャータイプ更新後

2015-07-28

属性値によるフィーチャーの出力先の振り分け

FME のライターは、各フィーチャーが持っている属性の値に応じて異なるフィーチャータイプ、データセットに振り分けて出力する機能を持っており、これを利用すると、ひとつのファイルに格納されているデータをある規則にしたがって複数のファイルに分割することも容易にできます。
ここでは、国土数値情報「ダム」データ(全国1ファイル)を都道府県別ファイルに分割するワークスペース例を掲げます。
FME 2015.1.1.0 build 15515

=====
国土数値情報「ダム」(Shapefile 形式, 全国1ファイル)を次のように分割する。
ケース1: 都道府県別ファイル
ケース2: 堤高50m未満、堤高50m以上に区分したサブフォルダ内の都道府県別ファイル
どちらのケースでも分割後のファイル名は "<都道府県コード (2桁数字)>_<都道府県名>.shp" とする。
各ダムが所在する都道府県は、属性(都道府県名から始まる所在地文字列)によって判別する。

ソースデータ
国土数値情報ダウンロードサービスサイトよりダウンロードした「ダム」 Shapefile 形式データ。
ダウンロードファイル名: W01-05-g_Dam.shp (全国1ファイル)
属性 "W01_007" に堤高 (数値), "W01_013" に都道府県名から始まる所在地 (文字列) が格納されている。
=====

ケース1: 都道府県別ファイル

FMEワークスペース例 1






















[SHAPE] リーダー: 国土数値情報「ダム」データを読み込む
JpPrefectureNameExtractor: 都道府県名から始まる所在地属性から都道府県名と都道府県コードを抽出する。
StringConcatenator: 都道府県別の出力先ファイル名を作成する。
[SHAPE] ライター: 各フィーチャーを都道府県別ファイルに振り分けて出力する。

結果1: 都道府県別ファイル

















JpPrefectureNameExtractor は「FMEサポート > 国内データ変換のサポート」ページで公開しているカスタムトランスフォーマーで、入力フィーチャーが持っている都道府県名から始まる住所や地名の属性文字列に基づいて都道府県名と都道府県コード (2桁の数字) を抽出し、それらを格納した属性を付加して出力します。デフォルトではそれらの属性名は "_pref_name" (都道府県名), "_pref_code" (都道府県コード) になりますが、パラメーター設定画面で他の属性名に変更することもできます。

JpPrefectureNameExtractor パラメーター設定画面














次に StringConcatenator によってアンダースコア "_" をはさんで都道府県コードと都道府県名を連結し、出力先のファイル名を作成しました。
StringConcatenator には2種類のパラメーター設定画面 (Basic モード, Advanced モード) があり、FME ワークベンチの初期設定では Basic モードで表示されます。

StringConcatenator パラメーター設定画面 (Basic モード)
左下 Switch To Advanced ボタンをクリックすると Advanced モードに切り替わります。





















StringConcatenator パラメーター設定画面 (Advanced モード)
左下 Options ボタンのクリックにより表示されるメニューで Switch To Basic を選択すると Basic モードに切り替わり、Default To Advanced Editor をチェックすると、次回以降 Advanced モードがデフォルトになります。





















以上のように出力先ファイル名を格納した属性を作成すれば、ライターフィーチャータイプのプロパティ設定画面 General タブの出力先フィーチャータイプ名フィールド (Shapefile 形式の場合は "Shape File Name") でそれを選択することにより、各フィーチャーの出力先を、その属性の値と等しい名前のファイルに振り分けることができます。

ライターフィーチャータイププロパティ設定画面 / General タブ















また、フィーチャータイプ名フィールドでは、テキストエディタによって StringConcatenator パラメーター設定画面 (Advanced モード) と同じ要領で出力先のフィーチャータイプ名とする文字列を作成することもできます。
この場合は StringConcatenator を省くことができます。

ライターフィーチャータイププロパティ設定画面 / General タブ / フィーチャータイプ名フィールド編集













ケース2: 堤高50m未満、堤高50m以上に区分したサブフォルダ内の都道府県別ファイル

出力先とするサブフォルダ名を格納した属性をフィーチャーに追加したうえで、ライターの Fanout Dataset (データセット振り分け) パラメーターを設定します。

FMEワークスペース例 2






















ケース1のワークスペースのライターフィーチャータイプの前に AttributeCreator を挿入し、Conditional Value (条件別の値) 設定機能により、堤高を格納している属性 "W01_007" の値が 50 未満であるかどうかに応じた文字列 (「堤高50m未満」または「堤高50m以上」) を「堤高区分」属性に格納しました。
これを出力先のサブフォルダ名とします。

AttributeCreator パラメーター設定画面 (Conditional Value 設定)
















Navigator ウィンドウでライターの Advanced / Fanout Dataset パラメーターをダブルクリックして Edit Fanout Dataset Paramters 画面を開き、Fanout Dataset (データセット振り分け) 用のパラメーターを設定します。

Fanout Dataset パラメーターの設定













Fanout Dataset: Yes  (データセットの振り分けをする)
Fanout Folder: <出力先のルートフォルダパス>
Attribute to Fanout on: 堤高区分  (出力先のサブフォルダ名を格納した属性)

結果2: 堤高区分別サブフォルダ/都道府県別ファイル

















Shapefile 形式の場合はフォルダがデータセット、ファイルがフィーチャータイプに対応するので、Fanout Dataset パラメーターの設定ではフォルダのレベル、出力先フィーチャータイプ名の設定ではファイルのレベルでフィーチャーの出力先が振り分けられます。
しかし、フォーマットによっては、ファイルがデータセット、ファイル内のフィーチャータイプ区分(レイヤ、クラス、テーブルなど呼び方はさまざま)がフィーチャータイプに対応するものもあり、そのようなフォーマットの場合は、Fanout Datset ではファイルのレベル、出力先フィーチャータイプ名ではレイヤ等のレベルで振り分けられることになります。
データの物理的な保存形態のどのレベルがデータセット、フィーチャータイプに対応するかはフォーマットによって異り、それに応じてどのレベルで出力先が振り分けられるかも異なることに注意してください。

国土数値情報「ダム」Shape形式データ属性テーブルのほとんどのレコードでは "W01_013" フィールドに所在地 (都道府県名から始まる住所や地名) が記録されていますが、ごく一部、そのフィールドが空白のレコードもありました。
JpPrefectureNameExtractor トランスフォーマーは、指定された属性文字列によって都道府県が識別できなかったとき、そのフィーチャーを Failure ポートから出力します。全てのデータを都道府県別ファイルに移行するためには、それらについて他の手段 (例えば既存の都道府県ポリゴンとの空間的な位置関係) によって所在地の都道府県を判別するべきでしょうが、この記事はフィーチャータイプ名、Fanout Dataset によって出力先を振り分ける方法を説明することがメインテーマなので、ワークスペース例では割愛しました。

2015-07-25

文字列の分割とリスト属性の展開

同一の地物が同じ属性項目について不特定数の値を持ちうる場合、属性データの格納方法としてテーブル形式しかサポートしていないフォーマットではカンマなどで区切って連結したひとつの文字列として記録せざるを得ないことがありますが、そのままでは、個々の値での検索を行いたい場合など不便なこともあります。

FMEには同じ名前で複数の値が格納できる「リスト属性」の仕組みがあり、ひとつの文字列を特定の文字で分割してリスト属性に変換することや、フィーチャーをリスト属性の要素数分コピーして各要素の値をコピー後のフィーチャーに配分すること(「リスト属性の展開」と呼ぶことにします)ができます。

ここでは、国土数値情報「医療機関」 Shapefile 形式データにおいて全角空白区切りで複数の診療科目が列挙されている文字列属性を個々の診療科目を要素とするリスト属性に変換した後、それを展開することによって、診療科目による医療機関の検索が容易なテーブルを作成するワークスペース例を掲げます。

FME 2015.1.1.0 build 15515

=====
国土数値情報「医療機関」 Shapefile 形式データの属性テーブル (1医療機関1レコード) に基づき、各医療機関の診療科目ごとのレコードで構成されるCSVテーブルに変換する。

ソースデータ:
国土数値情報ダウンロードサービスサイトよりダウンロードした「医療機関」データ (Shapefile 形式)

国土数値情報「医療機関」属性テーブル: FME Data Inspector による表示










次の3つのフィールドに診療科目名(複数ある場合は全角空白区切り, P04_005, P04_006 は空白の場合もある)が記録されている。
P04_004 (診療科目1)
P04_005 (診療科目2)
P04_006 (診療科目3)
=====

FMEワークスペース例



















[SHAPE] リーダー: 国土数値情報「医療機関」データを読み込む。
AttributeRenamer: 属性名を分かり易い名称に変更する (必須ではないが作業し易くするため)。
StringConcatenator: 診療科目1~診療科目3 を区切り文字 (全角空白) をはさんで連結する。
AttributeSplitter: 連結後の文字列を分割して個々の診療科目を要素とするリスト属性に格納する。
AttributeRemover: 不要な属性を削除する。
ListExploder: 診療科目を格納したリスト属性を展開する。
[CSV] リーダー: CSVファイルにテーブルを出力する。

結果: FME Data Inspector による表示 (所在地の詳細は隠してあります)


























国土数値情報「医療機関」データでは診療科目は 3 つのフィールドに記録されており、それぞれ全角空白区切りで複数の診療科目が記述されています。2番目、3番目のフィールドは空の場合もあります。
個別の診療科目名への分割が1回の処理でできるよう、事前に StringConcatenator によってそれらの 3 フィールドの文字列を全角空白をはさんで連結し、「診療科目連結」属性に格納しました。

AttributeSplitter は文字列を分割するために非常によく使われるトランスフォーマーです。

AttributeSplitter パラメーター設定画面



















Attribute to Split: 診療科目連結  (分割する文字列を格納している属性)
Delimiter or Format String: <全角空白>  (区切り文字。画面上では見えないが全角空白を入力)
Trim Whitespaces: Both  (分割後文字列の前後の空白を削除する)
List Name: 診療科目  (分割後の文字列を格納するリスト属性名)
Drop Empty Part: Yes  (空の要素は削除する)

これによって、「診療科目連結」に格納されている属性文字列が全角空白文字で分割され、分割後の文字列、すなわち個々の診療科目名が「診療科目{}」というリスト属性に格納されます。リスト属性の各要素には、次のように {} 内でインデクス (0から始まる連番) を指定することによってアクセスできます。
診療科目{0}
診療科目{1}
診療科目{2}
...

リスト属性を展開すると、そのリスト属性以外の属性やジオメトリはリストの要素数分コピーされて展開後のフィーチャーに引き継がれます。ここでは、以後の処理では使われない属性が無用にコピーされるのを防ぐため、AttributeRemover によってそれらを削除しました。

また、このワークスペース例では行っていませんが、ジオメトリも不要なので、GeometryRemover によって削除しておいた方がベターです。あるいは、最終的に属性しか使用しないので、[SHAPE] リーダーではなく、[DBF] リーダーによって最初から属性テーブルのみを読み込むこともできます。

ListExploder がリスト属性の展開を行います。

ListExploder パラメーター設定画面




















List Attribute: 診療科目{}  (展開するリスト属性)
他のパラメーターはデフォルトのまま。

この設定で実行すると、「診療科目{}」の要素数だけ各フィーチャーがコピーされ、それらにリスト属性の個々の要素が配分されてリスト属性名と同じ名前の属性(この場合は「診療科目」)に格納されます。

Conflict Resolution パラメーターがデフォルトの "Use Original" (オリジナルを使う) であるときは、フィーチャーがリスト名と同じ名前の属性をすでに持っていた場合に元の属性値の方が維持され、リストの要素は失われます。この例では、リスト属性を展開する前のフィーチャーには「診療科目」属性がなく属性名が衝突することはないのでデフォルトのままにしていますが、属性名が衝突することがある場合で、その属性値をリスト要素の値に置き換える必要があるときには、このパラメーターを "Use Incoming List" (リストの要素を使う) に変更してください。

[2017-04-11 追記] FME 2016 以降では、"Use Incoming List" の方がデフォルトになっています。

[2017-04-11 更新] 文字列の分割、リスト属性の展開だけでなく、リスト属性を利用することによって実現できる処理はたくさんあります。Transformer Gallery において、リスト属性に関する処理を行うトランスフォーマーは、FME 2016 以前では Lists カテゴリー、FME 2017 では Attributes カテゴリーに格納されています。


補足: 構造化リスト (structured list) について

リスト属性には、次のようにドットをはさんで連結された「メンバー名」を伴うものもあります。メンバー名を伴わないリスト属性と区別するときには、この形態のリスト属性を「構造化リスト (structured list)」または「複合リスト (complex list)」と呼ぶことがあります。
-----
_list{}.member1
_list{}.member2
-----

構造化リストには、同じインデクスの要素グループとして、メンバー名 (上の例では "member1", "member2") で区別される複数の値を格納することができます。

例えば、Aggregator によって複数のフィーチャーのジオメトリを集約してマルチパートのジオメトリを持つひとつのフィーチャーを作成するとき、List Name パラメーターでリスト名を指定することにより、元のフィーチャーが持っていた全ての属性を構造化リストに格納して集約後のフィーチャーに与えることができ、そのメンバー名は元の属性名と等しくなります。例えば元のフィーチャーが "ID", "Name" という属性を持っていたならば、集約後のフィーチャーに与えられる構造化リストは次のようになります。
-----
_list{}.ID
_list{}.Name
-----

要素数はそのフィーチャーに集約されたフィーチャーの数に等しく、インデクスが同じ要素グループが集約前のひとつのフィーチャーが持っていた属性の集合と対応します。

構造化リストを ListExploder によって展開したときは、各要素の値はメンバー名と同じ名前の属性としてコピーされたフィーチャーに配分されます。上の例の構造化リスト "_list{}" (ListExploder の List Name パラメーター選択リストではメンバー名の部分は表示されません) を展開すると、展開後のフィーチャーに配分されたリストの要素の格納先の属性名は "ID", "Name" になります。メンバー名を持たないリストとの違いに留意してください。

2015-07-23

複数のデータファイルの一括読込

FMEによって複数のファイルで構成されるデータセットを一括して読み込む場合、リーダーの Dataset の設定において、同じフォルダ内の複数のファイルを指定するだけでなく、複数のフォルダを選択したりファイルパス文字列のパターンによってフィルタリングしたりするなどにより、ディスクシステムのフォルダ構造やファイルの配置を変更する手間をかけずに必要なファイルを選択することができます。

ここでは、最も単純なデータ統合のケースとして、複数のファイルに分割して格納されているデータセットについて、フォーマットやスキーマの変更をせずにひとつのデータファイルに統合することを例として、それらのファイルを一括して読み込むためのリーダー Dataset の設定方法を説明します。

FME 2015.1.1.0 build 15515

=====
国土数値情報「行政区域」(平成27年1月1日時点, Shape形式)47都道府県をひとつのShapeファイルに統合する。

ソースデータ:
国土数値情報ダウンロードサービスサイトからダウンロードした「行政区域」データ
平成27年1月1日時点, Shapefile 形式, 47都道府県(47ファイル)
ダウンロードファイル名: N03-15_xx_150101.shp (xxは都道府県コード: 01~47)

ディスクシステムにおけるファイルの配置
ケース1: ひとつのフォルダ内に全てのファイルが保存されている(サブフォルダなし)
ケース2: ひとつのフォルダ内の地方別のサブフォルダに分けて保存されている
ケース3: ひとつの zip ファイルに全てのファイルがアーカイブされている
ケース4: ひとつのフォルダ内に解凍前の都道府県別 zip ファイルが保存されている
=====

FMEワークスペース例











[SHAPE] リーダー: 全てのファイルから全てのフィーチャーを読み込む。
[SHAPE] ライター: 全てのフィーチャーをひとつのファイルに出力する。

ワークスペースの内容は、[SHAPE] リーダーの Dataset の設定を除いてどのケースでも同じです。

まず、Workbench メニュー: Readers > Add Reader で Add Reader 画面を開き、Format フィールドで Esri Shapeを選択するとともに、Workflow Options で Single Merged Feature Type を選択します。

Add Reader 画面














Shapefile 形式の場合はファイルがフィーチャータイプに対応するので、Workflow Options を Individual Feature Type (デフォルト) のままにした場合、キャンバスにはファイル数分のフィーチャータイプが現れます。

これを Single Merged Feature Type に変更すると、キャンバスには <All> リーダーフィーチャータイプがひとつだけ現れ、全てのファイルから読み込まれたフィーチャーがそこから出力されるようになります。


ケース1: ひとつのフォルダ内に全てのファイルが保存されている(サブフォルダなし)


















このケースでの Dataset フィールドの設定方法は次の2通りが考えられます。

(a) Dataset フィールド横の[...]ボタンでファイル選択画面を開き、全ての Shapefile ファイルを選択する。

Shift キーを押しながら最初と最後のファイルをクリックすると、全てのファイルが選択できます。
















(b) Advanced Browser によって Shape ファイルを格納しているフォルダを選択する。

[2017-04-11 追記] FME 2017 では、Dataset フィールドの右端はメニューボタンとなり、それをクリックして開くメニューから "Select Multiple Folders/Files" (複数のファイル/フォルダーを選択) を選択することによって、複数のファイル/フォルダー選択用のダイアログボックス (下図右) が開きます。Workbench のユーザーインターフェースで Advanced Browser という名称は使われなくなりましたが、操作方法は従来と同じです。










Advanced Browser (右図) をOKで閉じると、Add Reader の Dataset フィールドは次のように設定されます。ここで、* (アスタリスク1個) は任意の文字列を意味し、選択したフォルダ内の全ての *.shp ファイルが読み込まれることになります。日本語版Windowsでは、バックスラッシュ \ を半角 ¥ に読み替えてください(以下同じ)。
-----
C:\Data\KSJ-N03-15\Case1\*.shp
-----

なお、デフォルトでは、リーダーをワークスペースに追加するときにワークベンチは全てのファイルのスキーマ定義を参照してリーダーフィーチャータイプを構成しますが、Advanced Browser 画面左下の Identical Schema チェックボックスをチェックすると、最初のファイルのスキーマ定義のみに基づいてリーダーフィーチャータイプを構成するようになります。読み込もうとする全てのファイルの属性定義が同一である場合は、これをチェックすることによってリーダーフィーチャータイプを構成する時間を短縮することができます。ただし、ワークスペースの実行時にフィーチャーを読み込む時間は変わりません。


ケース2: ひとつのフォルダ内の地方別のサブフォルダに分けて保存されている


















Advanced Browser では検索の対象とするフォルダをいくつでも追加することができるので、全ての地方別サブフォルダを選択することもできます。

しかし、さらに簡易な方法として、上位フォルダのみを選択して Subfolders チェックボックスをチェックすると、選択したフォルダ及びそれ以下の全てのサブフォルダ内の *.shp ファイルを検索することができます。
















この設定で Advanced Browser をOKで閉じると、Add Reader の Dataset フィールドは次のように設定されます。ここで、** (アスタリスク2個) は、その直上位のフォルダおよびそれ以下にある全てのサブフォルダを意味します。
-----
C:\Data\KSJ-N03-15\Case2\**\*.shp
-----


ケース3: ひとつの zip ファイルに全てのファイルがアーカイブされている


FMEは、ファイルベースのフォーマット用のリーダーの Dataset に zip 形式の圧縮ファイル (拡張子 .zip) が指定されたときに、それを自動的に解凍してから読み込みます。その場合、zip ファイルはフォルダと同じように扱われます。ただし、圧縮は1段階である場合のみをサポートします(アーカイブ内にある zip ファイルは解凍されません)。

Dataset フィールド横の[...]ボタンでファイル選択画面を開き、ファイルの種類ドロップダウンリストの選択を "Zip Files (*.zip)" に変更すると *.zip ファイルが選択できるようになります。
















ファイル選択画面を [開く] で閉じると、Add Reader の Dataset フィールドは次のように設定されます。
-----
C:\Data\KSJ-N03-15\Case3\N03-15.zip
-----
zip アーカイブ内にフォルダ階層がある場合には、それらをサブフォルダとみなしてファイルを検索することができます。その場合は、Dataset フィールドを次のように編集してください。
-----
C:\Data\KSJ-N03-15\Case3\N03-15.zip\**\*.shp
-----

zip ファイルの解凍は、ワークスペースの実行時にデータの読込が始まる前に行われます。解凍されたファイルはFMEの作業用フォルダに格納され、そのワークスペースによる変換が全て終了したときに自動的に削除されます。


ケース4: ひとつのフォルダ内に解凍前の都道県別 zip ファイルが保存されている





















Dataset の設定は次の手順で行うのが簡単です。

(1) Advanced Browser で上位フォルダを選択する。
















(2) File/Filter を *.zip\**\*.shp に修正する(ダブルクリックすると編集できます)。
















Advanced Browser をOKで閉じると、Add Reader の Dataset フィールドは次のように設定されます。
-----
C:\Data\KSJ-N03-15\Case4\*.zip\**\*.shp
-----

この設定により、Case4 フォルダ内の全ての *.zip アーカイブに格納されている全ての *.shp ファイル(アーカイブ内のサブフォルダ内を含む)を読み込むことになります。アーカイブ内にフォルダ階層がないことが明らかな場合は、中間の \** を省くことができます。


全ての場合において、Dataset フィールドで直接編集しても構いません。また、リーダーをワークスペースに追加した後、Navigator ウィンドウで変更することもできます。上記のケースを応用すれば、どんなディレクトリ構造でソースデータセットが格納されていても、ファイルを検索すべきフォルダを選択することができます。

2015-07-20

データベースとの連携 - データベースからのデータ抽出

データベースを利用することの利点のひとつとして、さまざまな条件でのデータ抽出がし易いということが挙げられます。FMEでデータベースからデータを抽出するには、リーダーを使用する他、SQL文によるクエリ(問い合わせ)によって行うこともできます。
ここでは、「データベースとの連携 - データベースへのデータ移行」において国土数値情報「鉄道時系列」データを移行して作成した PostGIS データベース "KSJ_Railroad2" からデータを抽出するワークスペース例を掲げます。
FME 2015.1.0.3 build 15485

1. リーダーによるデータ抽出 - WHARE Clause パラメーター

FMEがサポートする DBMS (データベース管理システム) については、それぞれに対応するリーダーがあり、それによってデータベースからデータを読み込むことができます。

FMEワークスペース例1: [POSTGIS] リーダーによるデータ抽出














リーダーをワークスペースに追加する際に、データベースに接続するためのパラメーターを設定するとともに、データベーステーブルを選択します。
データベース接続用のパラメーターの構成は DBMS によって異なります。PostgreSQL/PostGIS のパラメーターについては、「データベースとの連携 - データベースへのデータ移行」で説明した [POSTGIS] ライターのパラメーターを参照してください。

[POSTGIS] リーダーの追加: Add Reader画面, パラメーター設定画面, テーブル選択画面













この設定でリーダーをワークスペースに追加すると、キャンバスには RailroadSection, Station テーブルに対応するリーダーフィーチャータイプが現れ、それらに Inspector を接続して実行すると、データベースに格納されている全てのフィーチャー(レコード)が読み込まれることが確認できます。

データベース用のリーダーフィーチャータイプでは、WHERE Clause パラメーターでデータの抽出条件を設定することができます。抽出条件の書き方は SQL SELECT 文における WHERE 句の構文と同じです。
例えば、2000年における鉄道の整備状況を表すデータを抽出するには、リーダーフィーチャータイププロパティ設定画面で WHERE Clause パラメーターを次のように設定します(Navigator ウィンドウでも設定できます)。

[POSTGIS] リーダーフィーチャータイププロパティ設定画面 Format Parameters タブ
WHERE Clause: 設置期間_開始 <= 2000 and 2000 <= 設置期間_終了















WHERE Clause パラメーターを設定せずに全てのレコードを読み込み、データフロー内で Tester 等によってフィルタリングすることもできますが、通常は、WHERE Clause ではじめからデータを絞り込んだ方が効率が良くなります。

2000年に固定するのではなく、ワークスペースを実行するときに任意の年次を指定したいという場合は、年次の値をユーザーパラメーターとして設定できるようにしておくと便利です。
まず、Navigator ウィンドウの User Parameters/Published Parameters を右クリックして Add/Edit User Parameter 画面を開き、次のようにパラメーターを定義します。

[YEAR] パラメーター定義












そして、2つのリーダーフィーチャータイプの WHERE Clause パラメーターを次のように変更します。

[POSTGIS] リーダーフィーチャータイププロパティ設定画面 Format Parameters タブ
WHERE Clause: 設置期間_開始 <= $(YEAR) and $(YEAR) <= 設置期間_終了















ここで、"$(YEAR)" は、"YEAR" パラメーターを参照していることを表しており、ワークスペースの実行時にその値に置き換えられます。"YEAR" パラメーターにある年次を指定してから実行すれば、その年次の鉄道整備状況を表すデータが抽出できるというわけです。


2. SQL文によるデータ抽出: SQLCreator トランスフォーマー

ソースデータセットがデータベースである場合は、SQLCreator を使って SQL SELECT文によってデータを抽出することもできます。

FMEワークスペース例2: SQLCreator によるデータ抽出
















SQLCreator パラメーター設定 (鉄道路線)














Dataset グループでは、リーダーと同様にデータベース接続用のパラメーターを設定し、SQL Statement パラメーターで、データを抽出するためのSQL文を定義します。リーダーフィーチャータイプの WHERE Clause パラメーターと同様に、ここでもユーザーパラメーターを参照することができます。
-----
(YEAR年における鉄道路線抽出用のSQL文)
select * from "RailroadSection"
where 設置期間_開始 <= $(YEAR) and $(YEAR) <= 設置期間_終了
-----
(YEAR年における鉄道駅抽出用のSQL文)
select * from "Station"
where 設置期間_開始 <= $(YEAR) and $(YEAR) <= 設置期間_終了
-----
Attributes to Expose パラメーターで、インターフェースに表示させる属性名を設定します。この例では全てのフィールド名を設定しています。

SQLCreator には入力ポートがなく、ワークスペースを実行するとパラメーターの設定に基づいてデータベースからデータを抽出し、フィーチャー(レコード)をひとつずつ出力します。リーダーと同じにように働き、実行結果もリーダーを使用したワークスペース例1と全く同じになります。


3. SQL文によるデータ抽出: SQLExecutor トランスフォーマー

データ抽出条件が比較的単純で、かつ、1回の実行時にひとつの条件でデータを抽出するだけで良いという場合は、リーダーを使うのがシンプルで良いと思います。しかし、次のシナリオ例のように、異なる条件によって何度かデータを抽出するとともに、それらの結果に対して加工もしたいというような場合など、データフローの途中で SQLExecutor によってデータを抽出するのが効果的なこともあります。
=====
[シナリオ]
新幹線の路線(「事業者種別」 = 1 の路線)について、1960年代, 1970年代, 1980年代, 1990年代, 2000年代の10年ごとの区分で、各年代に「設置期間_開始」が含まれる区間を抽出する。
異なる年代の間で重複する区間については1本のラインにし、最も早い「設置期間_開始」の年代に区分する。
ラインに年代区分別の色を与え、KML形式のファイルに出力する。
=====

FMEワークスペース例3: SQLExecutor によるデータ抽出












Creator: 年代の区分数 = 5個のフィーチャーを作成する。
AttributeCreator: 各年代の開始年と終了年翌年の値を求めて属性に格納する。
SQLExecutor: データベースから各年代に「設置期間_開始」が含まれる新幹線の路線を抽出する。
LineOnLineOverlayer: 重複する区間をひとつのラインに統合する。
ListSorter: 元のラインの属性を格納したリストの要素を「設置期間_開始」の昇順でソートする。
ListIndexer: リストの先頭の要素(「設置期間_開始」が最も早いもの)をその区間の属性とする。
KMLStyler: KMLの表示スタイル(年代区分別の色)を設定する。
[OGCKML] ライター: KMLファイルに出力する。

結果: Google Earth による表示
















Creator で年代の区分数 = 5個のフィーチャーを作成して出力順を表す属性 i (0から始まる連番)を与え、AttributeCreator で i に基づいて各年代の開始年と終了年翌年の値を求めてそれらを属性 yearBeg, yearEnd に格納します。これで、ひとつのフィーチャーがひとつの年代区分を表すことになります。

SQLExecutor パラメーター設定





















SQL Statement パラメーターに次のSQL文を設定することによって、入力フィーチャー(年代区分)ごとに、その yearBeg から yearEnd の前年の間に「設置期間_開始」が含まれる新幹線の路線のデータを抽出します。
-----
select 路線名, 設置期間_開始, geom from "RailroadSection"
where 事業者種別 = 1
and @Value(yearBeg) <= 設置期間_開始 and 設置期間_開始 < @Value(yearEnd)
-----
SQLExecutor のSQL文では、@Value(属性名) によって入力フィーチャーの属性値をSQL文に埋め込むことができます。また、geom は空間データを格納しているフィールド名です。このフィールドの値を抽出することにより、ジオメトリが作成されます。ただし、前出 SQLCreator のSQL文のように * (アスタリスク) によって全てのフィールドの値を抽出する場合は書く必要はありません。
Combine Attributes パラメーターで "Keep Initiator Attributes if Conflict" を選択し、出力フィーチャーにはデータベースから抽出した属性だけでなく、Initiator ポートから入力されたフィーチャーの属性 (yearBeg, yearEnd) も付加されるようにしました。yearBeg (年代の開始年) によって年代が識別されます。

LineOnLineOverlayer は、入力されたラインのうち重複する区間を分離してひとつのラインに統合し、元のラインが持っていた属性を List Name パラメーターに指定した名前のリストに格納します。
ListSorter によってそのリストの要素を「設置期間_開始」の昇順でソートしたうえで、ListIndexer によって先頭の要素を取り出しました。これにより、複数の年代で重複していた区間は最も早い年代に区分できます。

もう少し工夫すると、年代区分別に5回データを抽出するのではなく、次のSQL文により1回の問い合わせで済ますこともでき、これを採用するならば SQLCreator を使うことになります。
-----
select 路線名, 設置期間_開始, geom,
case
    when 設置期間_開始 < 1970 then 1960
    when 設置期間_開始 < 1980 then 1970
    when 設置期間_開始 < 1990 then 1980
    when 設置期間_開始 < 2000 then 1990
    else 2000
end as "yearBeg"
from "RailroadSection" where 事業者種別 = 1 and 設置期間_開始 < 2010
-----

注: PostgreSQL/PostGIS データベース用のSQL文では、英大文字が含まれるテーブル名やフィールド名は二重引用符で囲む必要があります。これはFMEの仕様ではなく、PostgreSQL/PostGISの仕様であり、他のDBMS (データベース管理システム) のデータベース用のSQL文については適用されません。

2015-07-19

データベースとの連携 - データベースへのデータ移行

大規模なデータセットから異なる条件によって何度もデータ抽出を行わなければならないようなケースでは、あらかじめ全てのデータをデータベースに移行しておき、それをデータ抽出用のワークスペースのソースデータセットとして利用することによって、データ抽出に要する時間が劇的に短縮できる可能性があります。
ここでは、国土数値情報の鉄道時系列データを PostGIS データベースに移行するためのワークスペース例を掲げます。実用上は鉄道時系列データをデータベース化することに大きな意味はありませんが、属性の内容からみてさまざまなデータ抽出の例を考えやすいことから、サンプルとしました。
データベースからデータを抽出するためのワークスペースについては「データベースとの連携 - データベースからのデータ抽出」を参照してください。
FME 2015.1.0.3 build 15485

=====
国土数値情報の鉄道時系列データ(平成25年度作成; 路線, 駅)を PostGIS データベースに移行する。
データベース名: KSJ_Railroad2
テーブル名: RailroadSection, Station

ソースデータ:
国土数値情報ダウンロードサービスサイトよりダウンロードした鉄道時系列 Shapefile 形式データ(平成25年度)
ダウロードファイル名: "N05-14_RailroadSection2.shp" (路線), "N05-14_Station2.shp" (駅)
=====

FMEワークスペース例












[SHAPE] リーダー: 鉄道時系列データ(路線、駅)を全て読み込む。
[POSTGIS] ライター: RailroadSection テーブル、Station テーブルにフィーチャー(レコード)を挿入する。

鉄道時系列データ (Shape形式) には座標系定義ファイル (*.prj) が含まれていませんが、世界測地系(JGD2000)緯度経度であることは知られているので、[SHAPE] リーダーの Coordinate System パラメーターに LL-JGD2K (JGD2000緯度経度) を設定しました。これにより、読み込まれたフィーチャーに座標系が設定され、移行先のデータにも座標系が定義されます。その他にはソースデータの読込に関して特筆すべき事項はありません。

データベースの場合、データベースがデータセット、テーブルがフィーチャータイプ、レコードがフィーチャーに相当します。データベース(データセット)を新たに作成する場合は、あらかじめ空のデータベースを作成しておく必要があり、その方法はDBMS (データベース管理システム) によって異なります。PostgreSQL/PostGIS の場合は pgAdmin III (PostgreSQL に付属するデータベース管理用ツール) を使うのが簡単です。
なお、現在 FME は日本語文字を含む PostgreSQL/PostGIS データベース名をサポートしていないので、データベース名は英文字のみとしてください。この例では "KSJ_Railroad2" としました。テーブル名、フィールド名では日本語文字も使用できます。

データベース用のライターをワークスペースに追加する際には、データベースに接続するためのパラメーターの設定が必要です。パラメーターの構成も DBMS によって異なります。

[POSTGIS] ライター追加時の Add Writer 画面, パラメーター設定画面
"Database Connection" グループでデータベースに接続するためのパラメーターを設定します。














Add Writer 画面
Format: PostGIS
Dataset: Embed Connection Parameters

PostGIS Parameters 画面
Host: データベースサーバーのホスト名
Port: データベースサーバーの接続ポート番号
Database: KSJ_Railroad2  (データベース名 = データセット名)
Username: データベースユーザー名
Password: データベースユーザーのパスワード
Spatial Column Type: geometry  (デフォルト)
Spatial Column Name: geom  (デフォルト)
Create Generic Spatial Columns: チェック (デフォルト)
Lower Case Attribute Names: 列名(属性名)に英大文字を使用する場合はチェックをはずす。

ホスト名、接続ポート番号は、実際のデータベースサーバーの構成にしたがってください。データベースユーザーは、使用するデータベースに対するテーブル作成/削除、レコード挿入の権限を持っていなければなりません。

ライターを追加したら2つのライターフィーチャータイプ(テーブル)をキャンバスに追加し、それぞれのテーブル名と属性を設定します。ソースデータ(Shapeファイル)の属性定義については、国土数値情報ダウンロードサービスサイトの鉄道時系列データ説明ページ、及びそのページからリンクしている製品仕様書 (PDF) やShapeファイルの属性定義 (Excel) を参照してください。

[POSTGIS] ライターフィーチャータイププロパティ: RailroadSection 属性(フィールド)設定例





















ワークスペースの実行(データ移行)が一回限りの場合はこのままで良いですが、属性名やデータ型を変更して再実行する場合は、データの書出を始める前に、前回作成したテーブルを削除する必要があります。そのようなことが想定される場合は、フィーチャータイププロパティの Format Parameters タブで、Drop Table First (最初にテーブルを削除する) を Yes に変更してください。これにより、ワークスペースを実行するたびに、データベース内に同じ名前のテーブルが存在していた場合はそれが削除され、新たにテーブルが作成されるようになります。

[POSTGIS] ライターフィーチャータイププロパティ: Format Parameters タブ
















ソースデータのフィーチャータイプとライターフィーチャータイプ (RailroadSection, Station) を接続し、それらの間で対応する属性同士も接続すれば完成です。このワークスペースを実行すると、Shapeファイルから読み込まれた全ての鉄道時系列データ(路線、駅)が KSJ_Railroad2 データベース(RailroadSection テーブル、Station テーブル)に移行されます。

KSJ_Railroad2 データベース (pgAdmin III)
RailroadSection, Station テーブルが作成されました。
























Station テーブル (pgAdmin III クエリーツール)
空間データ(ポイントジオメトリ)は "geom" フィールドに記録されています。
















ここで掲げたワークスペース例では、リーダーフィーチャータイプとライターフィーチャータイプの間で属性をひとつずつ接続していますが、データフローの途中で AttributeRenamer などによってフィーチャーの属性名を出力先の属性名と同じ名前に変更した場合は、個々の属性同士の接続を明示的に行う必要はありません。また、不要な属性を削除したり、新たな属性を加えてそれもデータベースに移行したりするなど、必要に応じてデータ移行とあわせてスキーマを変更することもできます。

FMEではファイルベースのデータセットと同じ感覚でデータベースを取り扱うことができますが、データベースと接続するためのパラメーターなど、DBMS (データベース管理システム) ごとに少しずつ異なるところがあるデータベースの利用方法に関する基礎的な知識は必要です。初めてデータベースを扱う場合には、その点で少し難しさを感じるかも知れませんが、データベースシステム開発や運用の専門家を目指すのでない限りは、学ぶべきことはそんなに多くはありません。データベースが利用できるようになるとFMEの活用の幅も格段に広がりますので、是非、チャレンジしてください。

注: FME Professional エディションは、PostGIS データベースについては空間データの Read (読込), Write (書出) ともにサポートしていますが、Oracle, Microsoft SQL Server データベースへの空間データの Write はサポートしません (非空間データの Read/Write, 空間データの Read はサポートします)。それらのデータベースに空間データを書き出すには、FME Database エディションのライセンスが必要です。