 | レベル: 中級 Knut Stolze, pureXML and the DB2 Spatial Extender to support the Geography Markup Language (GML),DB2 z/OS Data Warehouse Accelerator, IBM Germany Research and Development, IBM
2008年 07月 18日 Geography Markup Language (GML) は、地理的な特性についての情報、およびそれに関連する属性をXML文書で表現するために作り替えられたXMLスキーマです。IBM DB2® などの多くの主要なデータベース・システムが、XML文書をネイティブに処理する機能を備えています。GML文書をDB2データベースに保管する一方で、実際の地理的な部分は DB2 Spatial Extenderおよびその空間タイプ階層によって管理するという方法を学習します。
はじめに
DB2 はバージョン 9以降、DB2データベースのXMLデータを効率的に保管、管理、照会し、XQueryによってデータを照会する pureXML を備えています。Geography Markup Language (GML) は、空間オブジェクトおよび地理オブジェクトの記述言語です。GMLは、XMLに基づいており、一連のXMLスキーマを定義します。現在、多くの空間データ (地理データが空間データの中で最も重要なサブセットとなっています) が、GML文書でデータ交換されています。そのため、データベースからそのままGML文書を取り出して合成したり、そのままの書式でXML対応のデータベースに保管したりできることが非常に重要になります。
DB2 Spatial Extenderは、DB2データベースの追加機能です。この追加機能には、特殊なデータ型、索引付け方式、空間データをネイティブに処理するルーチンが含まれています。点、線、多角形などの基本的なすべての地理オブジェクトについてデータ型が存在します。さらに、そのような基本オブジェクトの集合は、複数の点、線、多角形のスカラー値としても処理されます。Extenderを使用すれば、ジオメトリーに空間処理関数を適用できます。例えば、DB2はST_Distanceという名前の単純な関数を呼び出して、2つのオブジェクト間の距離を計算できます。
空間情報を表現する方法は、GMLとDB2 Spatial Extenderタイプ階層ではかなり違います。この記事では、DB2のpureXML機能を活用してGML文書を処理し、これをDB2 Spatial Extenderを使用して連携する方法について学習します。GML文書をDB2データベースにインポートし、文書から空間情報を抽出し、それをDB2 Spatial Extenderが理解できるジオメトリー・オブジェクトとして保管する方法を確認してください。同様に、DB2データベースからGML文書を取り出して合成する方法についても理解してください(pureXMLおよびDB2 Spatial Extenderの基本に関する詳細については、「参考文献」セクションを参照してください)。
次のセクションでは、文書サイズが約24.1MBのGMLサンプル・データを使用します。サンプル・データは、グレートブリテン島の「OS MasterMap」です。これは、Snowflake Softwareサイトからダウンロードできます。リンクについては「参考文献」セクションを参照してください。ファイル・サイズが大きくなったので、必要最低限のデータだけが含まれる、約5MBのバージョンを作成しました。
GML 文書を DB2 にインポートする
基本的な作業は、DB2データベースへのGML文書のインポートです。GMLは、基本的には単なるXMLスキーマ定義のセットです。GML文書もまたXML文書です。そのため、DB2に組み込まれているpureXML機能を直接利用できます。
この例では、ユーザー定義関数 (UDF) のLoadBLOBを使用して、ファイルからXML文書をBLOBに読み込んでいます。UDFはサーバー上のDB2プロセスで実行されるため、DB2サーバーからアクセス可能な同じファイル・システムにファイルが存在している必要があります。UDFのC++ソース・コードおよび関数を登録するためのSQLスクリプトが「ダウンロード」セクションにあります。リスト1では、XML_TESTという名前の表にデータをロードする方法を示します。表には、数字の識別子の列と、XML 型の単一列があるのが分かります。両方のXML文書 (全文書および短い文書の両方) が表に完全に挿入されます。
リスト1:DB2へのGML文書のロード
DROP TABLE xml_table@
CREATE TABLE xml_table (
id INTEGER NOT NULL PRIMARY KEY,
xml_data XML NOT NULL
)@
INSERT INTO xml_table
VALUES ( 1, XMLPARSE( DOCUMENT
loadBLOB('/home/stolze/gml-full-map.xml')) ),
( 2, XMLPARSE( DOCUMENT
loadBLOB('/home/stolze/gml-short-map.xml')) )@
|
DB2サーバーにあるファイルからデータを取得してデータベースに保管する方法としてUDFを使用できます。クライアントでGML文書が使用可能な場合には、GML文書をDB2サーバーに転送する必要があります。この記事では、それを目的とする小さなJavaプログラムを提供します (「ダウンロード」を参照してください)。DB2データベース名とデータベース接続に使用するユーザー資格情報を変更する必要があります。
もうお気付きのことと思いますが、上述の操作ではXML文書の内容を利用しません。文書全体が単一の列にそのまま保管されます。そのため、空間情報がGMLでエンコードされていることが考慮されず、DB2データベースでこのデータに対してネイティブに空間操作を実行できません。以下のセクションでは、空間情報を抽出し、データベースで適切に表現する方法について詳細に説明します。
GML文書からジオメトリーを抽出する
DB2は、XML文書を処理して、そのすべてまたは一部をリレーショナル表現に変換するXMLTABLE関数を提供しています。私の場合、XML文書を解析してGML情報を抽出するためにこの関数を使用します。また、現在DB2 Spatial Extenderも積極的に活用しています。そのためデータベースで空間操作を実行できるようになりました。
まず第一にすべきことは、GMLファイル内に存在する可能性がある情報の種類を判別することです。普通、この種類は、受け取って処理しようとしているGML文書によりすでに分かっています。新規文書の場合は、GMLデータに添付されているGML仕様とXMLスキーマ文書を参照する必要があります。私は、1回限りの試みとして別のアプローチを選び、このためにちょっとしたAWKスクリプトを作成しました。スクリプトは、下記のリスト2にあります。スクリプトでは、基本的にosgb名前空間内のそれぞれのXMLタグのネスト・レベルを数えます。その結果、GML文書には、cartographicMember、topographicMember、およびboundaryMemberという3つの異なるタイプのタグだけがあることが分かります。
リスト2:FeatureCollection下にネストされているGML要素を抽出するAWKスクリプト
BEGIN { depth = 0; }
{
if ( substr($1, 1, 6) == "<osgb:" ) { depth++; }
if ( depth == 2 ) { print $0; }
if ( substr($1, 1, 7) == "</osgb:" ||
index($0, "</osgb:"substr($1, 7, 5)) > 3 ||
( substr($0, length($0)-1) == "/>" &&
substr($1, 1, 6) == "<osgb:" ) ) { depth--; }
}
|
処理対象のGML文書に基づいて、文書を解析して、cartographicMember、topographicMember、およびboundaryMemberの各内容をリレーショナル表現に変換するSQLステートメントを作成するのが簡単です。cartographicMembers については、次の情報を抽出します。
- 機能ID(CartographicSymbolタグの属性fid)
- 機能コード
- テーマ
- 記述グループ
- 記述用語
- 物理レベル
- 点位置
点位置は、すでにGMLにエンコードされています。そのため、このタグは副選択にラップされて、点オブジェクトを作成するDB2 Spatial Extenderコンストラクターを呼び出すコールになります。それ以外の主な作業は、XML文書からリレーショナル・モデルへの列マッピングを定義することです。それに使用したSQL文をリスト3に示します。抽出されたXMLデータをファイルshredding.sqlに抽出する表の定義があります (「ダウンロード」を参照してください)。
リスト3:GML文書からの地図情報の抽出
INSERT INTO cartographic_data
SELECT x.id, t.id, t.code, t.theme, t.group, t.term, t.level,
db2gse.ST_Point(SUBSTR(
XSLTRANSFORM(t.point USING
'<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>' AS VARCHAR(1000)),
LENGTH('<?xml version="1.0" encoding="UTF-8"?>') + 1), 1)
FROM xml_table AS x,
XMLTABLE ( XMLNAMESPACES(
'http://www.ordnancesurvey.co.uk/xml/namespaces/osgb' AS "osgb",
'http://www.opengis.net/gml' AS "gml"),
'$d/osgb:FeatureCollection/osgb:cartographicMember'
PASSING x.xml_data AS "d" COLUMNS
id VARCHAR(20) PATH '*/@fid',
code INTEGER PATH '*/osgb:featureCode',
theme VARCHAR(100) PATH '*/osgb:theme',
group VARCHAR(100) PATH '*/osgb:descriptiveGroup',
term VARCHAR(100) PATH '*/osgb:descriptiveTerm',
level INTEGER PATH '*/osgb:physicalLevel',
point XML PATH '*/osgb:*/gml:Point' ) AS t
@
|
このSQLステートメントでは、説明が必要な点が 2、3あります。それでは、FROM節から見ていきましょう。osgbおよびgmlという2つの名前空間がXMLTABLE関数のXQuery式に使用されています。これらの2つの名前空間は、それぞれのXML要素が厳密に一致するように、GML文書で宣言するときに正確に定義する必要があります。組み込み関数XMLNAMESPACESを使用して、列生成式に加え、行を生成するXQuery式の2つの名前空間を定義します。2つ目の重要な点は、POINT列の列生成式です。osgb:anchorPointを使用して位置を指定するXML要素が存在するので、この記事の例ではosgb:pointの代わりにosgb:*を使用します。これはosgb:cartographicMember下に直接ネストされている要素に対しても同様に適用します。検索対象のosgb:CartographicText要素とosgb:CartographicSymbol要素があります。アスタリスク (*) は任意の要素に一致します。そのため、SQLステートメントは両方を処理し、いずれか一方を無視することはありません。
もう1つの複合式は、SELECTリスト内にあります。最初の行は簡単です。この行では、XMLTABLEによって生成された表から個々の列を返し、XML文書ID (XML_TABLE 表から取得します) も割り当てます。SELECTリストの最後のSQL式は、ST_Pointオブジェクトのコンストラクターを示します。これは、DB2 Spatial Extenderが提供するデータ型であり、点オブジェクトを表現するために使用されます。コンストラクターは、数字のSRS識別子に加え、点のGML表現を入力として取得します。この記事の例では、ID 1を持つ定義済みのSRSを使用します。GML文書で使用されるすべての座標を表現するのに十分な範囲があるからです。読者が使用したいと考える特定のSRSがあるかもしれません。しかし、gml:Point要素に名前空間情報が付加されているので、DB2 Spatial Extenderは、コンストラクターに渡されるGML表現を直接処理することができません。そのため、この記事の例では、すべての要素から名前空間情報を除去するXSLテンプレートを使用し、入力文書から抽出されたジオメトリーのGMLフラグメントにこのテンプレートを適用するためにXSLTRANSFORM関数を呼び出します。しかしXSLTRANSFORMを使用することで、文字ストリームの前にXML宣言<?xml version="1.0" encoding="UTF-8"?>が付加されるという別の問題が起こります。そのため、宣言を削除して残りのストリングのみを保持するSUBSTRを呼び出すコールを挿入します。
地図メンバーの抽出に用いたのと同じメカニズムを使用して、地形メンバーおよび境界メンバーの属性を取得します。異なる属性セットを使用できることが主な違いです。つまり、別々の表を使用して、リレーショナル方式で属性情報を格納します。また、ファイルshredding.sqlには、地形メンバーおよび境界メンバーを処理するSQLステートメントもあります(「ダウンロード」を参照してください)。
すべての手順を完了すると、次の表が作成されます。
- 表XML_TABLEには、識別された数値とともにXML文書が格納されます。
- 表CARTOGRAPHIC_DATAには、各XML文書から抽出されたcartographicMember要素に関する詳細情報が格納されます。ジオメトリー情報は、ST_Point値によって表現されます。
- 表TOPOGRAPHIC_DATAには、各XML文書から抽出されたtopographicMember要素に関する詳細情報が格納されます。地形データには線および多角形が用いられるので、ジオメトリー情報は ST_Geometry 値によって表現されます。
- 表BOUNDARY_DATAには、各XML文書から抽出されたboundaryMember要素に関する詳細情報が格納されます。ジオメトリー情報は、ST_LineString値によって表現されます。
抽出処理が終われば、簡単に空間機能を活用できます。例えば、ジオメトリー間の距離を計算したり、追加のデータ表で空間インデックスを作成したりできます。
GML文書の合成
このセクションでは、DB2データベースに保管されているリレーショナル・データに基づいて、いかに簡単にGML文書を合成できるかという点を説明します。このタスクは、基本的にシュレッディングの逆の処理になります。pureXMLを備えるDB2が、XML文書を作成するのに必要なインフラストラクチャーを提供します。DB2 Spatial Extenderには、保持している任意のジオメトリーをそれに対応するGML表現に変換できる機能があります。この機能をこのインフラストラクチャーと組み合わせることで、GML文書を作成できます。
引き続き、このセクションでも、前のセクションでGML文書を合成するために作成した表を使用します。具体的には、表CARTOGRAPHIC_DATAに対して照会を実行します。次のリスト4のこの表の構造をもう一度見てみましょう。
リスト4:表CARTOGRAPHIC_DATAの定義
CREATE TABLE cartographic_data (
doc_id INTEGER NOT NULL,
feature_id VARCHAR(20) NOT NULL,
feature_code INTEGER,
theme VARCHAR(100),
desc_group VARCHAR(100),
desc_term VARCHAR(100),
level INTEGER,
point db2gse.ST_Point,
CONSTRAINT cartographic_data_pk PRIMARY KEY ( doc_id, feature_id ),
CONSTRAINT doc_id_fk FOREIGN KEY(doc_id) REFERENCES xml_table(id)
)@
|
次のリスト5のSQL照会は、この表に対して実行されます。その結果、新しいGML文書が作成されます。
リスト5:地図メンバーのみのGML文書の合成
SELECT XMLDOCUMENT(XMLELEMENT(
NAME "osgb:FeatureCollection",
-- (1)
XMLNAMESPACES(
-- (1a)
'http://www.ordnancesurvey.co.uk/xml/namespaces/osgb' AS "osgb",
'http://www.opengis.net/gml' AS "gml",
'http://www.w3.org/1999/xlink' AS "xlinx",
'http://www.w3.org/2001/XMLSchema-instance' AS "xsi"),
XMLATTRIBUTES(
-- (1b)
'http://www.ordnancesurvey.co.uk/xml/namespaces/osgb ' ||
'http://www.ordnancesurvey.co.uk/xml/schema/v4/OSDNFFeatures.xsd'
AS "xsi:schemaLocation"),
XMLAGG(
-- (2)
XMLELEMENT(NAME "osgb:cartographicMember",
XMLELEMENT(NAME "osgb:cartographicText",
XMLATTRIBUTES(feature_id AS "fid"),
XMLELEMENT(NAME "osgb:featureCode", feature_code),
XMLELEMENT(NAME "osgb:theme", theme),
-- (3)
XMLELEMENT(NAME "osgb:descriptiveGroup", desc_group),
XMLELEMENT(NAME "osgb:point", XMLPARSE(DOCUMENT
-- (4)
XSLTRANSFORM('<nsWrapper xmlns:gml="http://www.opengis.net/gml">' ||
point..ST_AsGML() || '</nsWrapper>' USING
'<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="nsWrapper">
<xsl:apply-templates/>
</xsl:template>
<xsl:template match="*">
<xsl:element name="{local-name()}">
<xsl:copy-of select="@*"/>
<xsl:apply-templates/>
</xsl:element>
</xsl:template>
</xsl:stylesheet>' AS CLOB(2M)))))))))
FROM cartographic_data
GROUP BY doc_id
|
一見すると、複雑な照会に見えます。しかし、コメントの番号を参照しながら、1つずつSQLステートメントを見ていきましょう。最初の関数XMLDOCUMENTは、関数自体の入力に基づいて実際の XML 文書を作成します。入力は、ネストされている一連のXMLELEMENT関数コールで構成されます。最初のコール (1) によって osgb:FeatureCollectionという名前のXML文書のルートが作成されます。この要素に名前空間 (1a) およびその他の属性 (1b) が付加されます。ルート要素の下に osgb:cartographicMember要素の集合があります。それぞれの地図メンバーは CARTOGRAPHIC_DATA表の別々の行に格納されるので、それらの複数行を文書ごとに結合する必要があります。これは、XMLAGG 関数 (2) を、照会のGROUP BY節と共に使用して行います。各地図メンバーは、複数の要素から構成されます (3)。要素のテキスト値はCARTOGRAPHIC_DATA表の行から取り出され、各列名によって、どの値がどの属性に割り当てられるのか、どの値がネストされた要素のテキストなのかが識別されます。
空間データの処理は、これよりも少し複雑です。データはDB2 Spatial Extenderが提供するジオメトリー・タイプに格納されるので、XMLに変換する必要があります。ST_AsGML関数が、この変換を担当します。しかし、関数の結果がテキストとしてosgb:point要素に埋め込まれる場合は、すべてのXMLタグを実際に (適切に) エスケープします。GMLストリングのタグは実際にはネストされている要素を表していることをXMLELEMENT関数が認識できないからです。そのため、XMLPARSEステップが組み込まれています。また、関数XSLTRANSFORMも使用されていることが分かると思います。XMLPARSEが、「解析中のXML文書で名前空間gmlが定義されていない」というエラーで失敗するので、この関数コールが必要になります。ST_AsGMLによって返されるストリングは単なるXMLフラグメントであり、全体のGML文書の上位レベルで適切な名前空間が定義されていることに依存するので、このエラーは驚くものではありません。そうはいっても、これは決して歓迎すべき状況ではありません。そこで、XSLスタイルシートを使用して、GMLフラグメントの各タグの名前空間の表示を削除します。これが機能するには、GMLフラグメントで少なくとも1回は名前空間が定義されている必要があります。このために、この例ではST_AsGMLの出力を要素nsWrapperでラップしています。このラッピング要素もXSL変換によって削除されます。変換の結果として名前空間が削除されたXMLフラグメントが生成され、それが正常に解析されれば、最終的なGML文書にXML値として挿入されます。リスト6に、上記の照会で生成された出力の最初の部分を示します。
リスト 6: GML 文書を合成する照会のサンプル出力
1
------------------------------------------------------------------------------------------
<osgb:FeatureCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgb="
http://www.ordnancesurvey.co.uk/xml/namespaces/osgb" xmlns:gml="http://www.opengis.net/gml
" xmlns:xlinx="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.ordnancesurvey
.co.uk/xml/namespaces/osgb http://www.ordnancesurvey.co.uk/xml/schema/v4/OSDNFFeatures.xsd
"><osgb:cartographicMember><osgb:cartographicText fid="osgb1000000753251518"><osgb:feature
Code>10066</osgb:featur
<osgb:FeatureCollection xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:osgb="
http://www.ordnancesurvey.co.uk/xml/namespaces/osgb" xmlns:gml="http://www.opengis.net/gml
" xmlns:xlinx="http://www.w3.org/1999/xlink" xsi:schemaLocation="http://www.ordnancesurvey
.co.uk/xml/namespaces/osgb http://www.ordnancesurvey.co.uk/xml/schema/v4/OSDNFFeatures.xsd
"><osgb:cartographicMember><osgb:cartographicText fid="osgb1000000753251518"><osgb:feature
Code>10066</osgb:featur
2 record(s) selected.
|

 |
まとめ
この記事では、Geography Markup Language (GML) で定義されたXMLスキーマを使用して、空間情報がエンコードされたXML文書をDB2データベースで保管および管理する方法について説明しました。DB2のpureXML機能は、XMLデータを処理する豊富な機能セットを提供し、GML文書に対して直接この機能を活用できます。非空間属性については、特別な注意は必要ありません。空間情報だけは、多少の注意を払って処理する必要があります。これは、空間操作に専用のデータ型および関数を提供するDB2 Spatial Extenderが、GMLフラグメントは処理できても、名前空間など、すべてが含まれたXML文書を処理したり生成したりできないという理由からです。そのため、この記事の例ではXSL変換を適用してGMLフラグメントから名前空間情報を削除しました。この適応については、どの程度の正確さで GML文書がデータベースに保管され、マッピング・スキーマが定義されているかという点が主に重要になります。DB2 Spatial Extenderの機能をこの処理に使用することで、顕著なオーバーヘッドが生じることはなく、支障が生じることはありません。
ダウンロード | 内容 | ファイル名 | サイズ | ダウンロード形式 |
|---|
| この記事のサンプル・スクリプト | samples.zip | 11KB | HTTP |
|---|
参考文献 学ぶために
製品や技術を入手するために
議論するために
著者について  | 
|  | Knut Stolzeは、1999年に米国のSilicon Valley Labの客員研究員としてIBMに入社したときからDB2の取り組みを開始し、そこでDB2 Image Extenderについて研究しました。その後、DB2 Spatial Extender開発チームに移り、Extenderのユーザビリティー、パフォーマンス、および標準適応を向上させるいくつかの機能拡張を担当しました。2002年から2006年までKnut StolzeはドイツのUniversity of Jenaで修士課程生として学ぶかたわら、大学の助手を務めました。それと並行してInformation Integrator開発の分野でIBMでの研究も続けました。現在Knut Stolzeは、DB2 z/OSユーティリティーおよびDB2 for z/OS上のデータウェアハウジングを担当する開発チームのメンバーとなっています。 |
記事の評価
|  |