IBM®
本文へジャンプ
    Japan [変更]    ご利用条件
 
 
検索範囲検索:    
    ホーム    製品    サービス & ソリューション    サポート & ダウンロード    マイアカウント    
skip to main content

developerWorks Japan  >  Information Management | XML  >

DB2 pureXML を使って XML 文書をシュレッドする

DB2 for Linux, UNIX, and Windows で XML を分解する 2 つの方法

developerWorks
ページオプション

JavaScript を要するドキュメントオプションは表示されません

サンプルコード

原文はこちら

原文はこちら


レベル: 中級

Salvador Ledezma, Staff Software Engineer, IBM
Bert Van Der Linden (robbert@us.ibm.com), DB2 pureXML Architect, IBM

2008年 1月 03日

バージョン 9.1 以来、DB2 には XML データの保管、管理、検索を行うための重要なサポートが新たに備わっています。そんな新しい機能の 1 つが、アノテーション付き XML スキーマ分解機能です。アノテーション付き XML スキーマ分解により、XML 文書をリレーショナル表に分解 (すなわち「シュレッド」) することが可能になります。さらに XML 文書を分解するもう 1 つの方法として、SQL または XML 関数を使用した XMLTABLE も用意されています。この記事では XMLTABLE 関数を分解に使用する方法を含め、XML データを分解する 2 つの方法について説明します。さらに、アノテーション付き XML スキーマ分解と XMLTABLE 分解を比較し、それぞれに推奨される使用法を提案します。

はじめに

XML データは企業のなかで増え続けていますが、常に XML を XML として保管できるというわけでもありません。例えば、レガシー・データ・アーキテクチャーで作業していたり、あるいはその他の要件によってストレージをリレーショナルにできないという場合があるからです。実際、XML データとして送受信されるメッセージでも、元はリレーショナル・データから構成されたものであるためリレーショナル・データに分解されることも珍しくありません。このようにデータを XML として保管できない場合に役立つのが、DB2 の 2 つの機能、SQL/XML パブリッシング関数と XML 分解です。前者の SQL/XML パブリッシング関数はリレーショナル・データから XML データを構成するのに役立ちます。しかし、この記事では扱わないので、パブリッシング関数についての概要と DB2 で XML データにクエリーを実行する方法については、developerWorks の記事「SQL を使った DB2 XML データの照会」(developerWorks、2006年3月) を参照してください。

この記事では、DB2 で XML データを「シュレッド」する方法に焦点を当てます。シュレッディングとは、XML 要素および属性をリレーショナル表と列にマッピングするプロセスのことです。DB2 でシュレッディングを行うには、アノテーション付き XML スキーマを使用するという方法があります。XML データに XML スキーマが含まれている場合には、これが最も簡単かつ素早く分解を行う方法となります。マッピングが極めて複雑で複数の表が関わってくる場合、既存のツールによってマッピング手順と分解手順の両方を自動化します。

あまりよく知られていないかもしれませんが、SQL/XML の関数 XMLTABLE を使ってシュレッディングを行うという方法もあります。この方法が役立つのは XML スキーマが存在しない場合です。XMLTABLE 関数を使用すると複雑さが増す可能性がありますが、これは分解手順をハンド・コーディングしなければならなくなるためです。つまり、特定の XML 要素をどのように表と列にマッピングするかについて、開発者が XQuery 式を使って明示的に規定しなければなりません。しかしこの柔軟性こそが、XMLTABLE 分解をアノテーション付き XML スキーマ分解より強力な方法として、アノテーション付き XML スキーマ分解では不可能なマッピングでも実現できるようにしている理由です。

この記事ではいくつかの分解例を、アノテーション付き XML スキーマと XMLTABLE 関数の両方を使って説明します。さらに、アノテーション付き XML スキーマ分解ではサポートしない一方、XMLTABLE ではサポートする例も紹介します。そして最後に、それぞれの方法でのベスト・プラクティスを比較し、推奨される使用法を提案して記事を締めくくります。




上に戻る


アノテーション付き XML スキーマ分解

DB2 のアノテーション付き XML スキーマ分解機能は、XML 文書をリレーショナル表に分解するための機能です。その名前が示すとおり、この機能は XML スキーマ内のアノテーションをマッピング言語として使用して XML 文書に含まれる情報をリレーショナル表にマッピングします。このようにアノテーション付き XML スキーマ分解には XML スキーマが必要になるため、XML スキーマ文書が DB2 XSR (XML Schema Repository) に保管され、分解用に指定されていなければなりません。XML 文書をマッピング先のリレーショナル列に分解 (すなわち「シュレッディング」) するには、DB2 ストアード・プロシージャーの呼び出し、またはコマンド・ライン・プロセッサー (CLP) のコマンドを使用します。

XML スキーマにアノテーションを付けるには、IBM Data Studio を使用するという手段があります。無料でダウンロードできる Data Studio は、ストアード・プロシージャーとユーザー定義関数の開発を含め、DB2 データベース・アプリケーションの作成、編集、デバッグ、デプロイ、そしてテストを行うための包括的な統合開発環境です。ダウンロード情報については、この記事の「参考文献」セクションを参照してください。Data Studio のコンポーネントのなかには、アノテーション付き XML スキーマ分解マッピング・エディターがあります。このエディターでは単純かつ直観的なグラフィカル・インターフェースを使って XML スキーマとリレーショナル・スキーマとの関係をマッピングすることができます。グラフィック上で XML 要素または属性を DB2 のリレーショナル列にマッピングすると、XML スキーマ文書に自動的にアノテーションが付けられます。XML スキーマを保管して XSR に登録すれば、XML 文書を DB2 に分解する用意は完了です。

xdbDecompXML は、アノテーション付き XML スキーマ分解に使用する DB2 ストアード・プロシージャーです。xdbDecompXML にはいくつかのバージョンがあり、それぞれのバージョンが文書のサイズごとに最適化されています。各バージョンには以下の名前が付けられています。

  • XdbDecompXML
  • XdbDecompXML10MB
  • XdbDecompXML25MB
  • XdbDecompXML50MB
  • XdbDecompXML75MB
  • XdbDecompXML100MB

名前からわかるように、上記のストアード・プロシージャー間で異なる点は、分解する XML 文書のサイズだけです。例えば、1 MB までの XML 文書には xdbDecompXML を使い、10 MB までの XML 文書には xdbDecompXML10MB を使います。いずれのストアード・プロシージャーも 8 つのパラメーターを使用しますが、そのうちの 3 つは将来のために予約されているので NULL に設定してください。この 8 つのパラメーターは以下のとおりです。

  • rschema
    XML スキーマ・リポジトリーに登録された XSR オブジェクト名を構成する 2 つの部分のうち、SQL スキーマの部分です。
  • xmlschemaname
    XSR オブジェクト名を構成する 2 つの部分のうちの XML スキーマ名です。
  • xmldoc
    BLOB オブジェクトとして渡される、分解対象の XML 文書です。文書のサイズによって、呼び出すストアード・プロシージャーが決まります。
  • documentid
    分解対象の XML 文書の識別子です。この識別子は XML スキーマの特定のアノテーション (具体的には、db2-xdb:expression および db2-xdb:condition) で使用することができます。
  • validation
    分解対象の XML 文書を XML スキーマと照合して検証する必要があるかどうかを示す整数値です。0 は検証を行わないことを示し、1 は文書を検証することを示します。
  • reserved
    最後の 3 つの引数は将来のために予約されているので、NULL に設定します。

xdbDecompXML を呼び出すことにより、DB2 は XSR に保管された XML スキーマのアノテーションに基づいて XML 文書を分解し、適切なリレーショナル表に挿入することができます。

XML スキーマのアノテーションおよびストアード・プロシージャーの xdbDecompXML 一式についての詳細は、この記事の範囲外なので説明は省きます。アノテーション付き XML スキーマ分解について詳しく学ぶには、「DB2 Version 9 XML Guide」(この記事の「参考文献」セクションに記載) を参照してください。内容に基づく条件付き分解、あるいは適用するコンテンツ変換を指定してから挿入するなどの高度な機能を含めた詳細が記載されています。XML Extender とその分解方法について十分理解されている方は、「From DAD to Annotated XML Schema Decomposition」(developerWorks、2006年4月) で詳細を調べてください。




上に戻る


XMLTABLE 分解

アノテーション付き XML スキーマ分解では XSR に XML スキーマが存在することが条件となりますが、XMLTABLE 関数を使えば、XML スキーマがなくても文書を分解できます。XMLTABLE は、XQuery 式を評価して表を返す SQL 表関数です。返される表には、XML をはじめとするあらゆる SQL データ型の列を含めることができます。XMLTABLE に指定された XQuery 式に変数を渡すことも可能です。

XMLTABLE の一般的な構文は以下のようになります。


リスト 1. XMLTABLE の一般的構文
                
XMLTABLE( xquery-expression  PASSING xml-source 
COLUMNS 
column-name	column-(sql)data-type PATH path-xquery-expression
,...)

xml-source は、データを表形式の結果として提供する XML 文書です。これは DB2 の XML 列に保管された文書にすることも、DB2 外部の文書にすることもできます。引数 xquery-expression に指定された XQuery 式は、行を生成する XQuery 式です。行は各項目に対して出力順に生成されます。結果表の構造は、関数の COLUMNS 節によって定義されます。この COLUMNS 節では、列名 (column-name)、データ型 (column-(sql)data-type)、そして列の値を生成する方法を指定することで、列の特性を定義します。結果表の列の値は、XMLTABLE の PATH 節に XQuery 式 (path-xquery-expression) を指定することによって生成することができます。path-xquery-expression は、xquery-expression で選択された項目に関する列の値を指定します。詳細については、以降に記載する例を参照してください。

XMLTABLE を INSERT 文と組み合わせて使用すると、値を XML 文書内から取得してリレーションナル表に挿入できるので、アノテーション付き XML スキーマ分解と同じ機能が実現します。この XMLTABLE と INSERT 文との組み合わせは、よく「Insert-from-XMLTABLE」文と呼ばれますが、この記事では XMLTABLE 分解 (XMLTABLE decomposition) という言葉を使います。

INSERT 文に渡されるデータは、XMLTABLE 関数から返されるデータには限定されません。ホスト変数や別の表、そして他の XMLTABLE 文や表関数などをデータのソースとすることもできます。XQuery と SQL 両方の能力を利用する XMLTABLE 分解には、極めて高い柔軟性があります。しかし、INSERT 文が挿入先とする表はやはり 1 つだけです。複数の表への挿入が必要になるマッピングでは、XMLTABLE を呼び出す INSERT 文を複数定義する必要があります。このような理由から、XMLTABLE 分解文を SQL ストアード・プロシージャーで使用すると役に立つ場合があります。SQL ストアード・プロシージャーに文を定義すると、特定のマッピングでどんなに多くの表にデータを設定しようとも、アプリケーションは呼び出しを 1 回行うだけで済みます。さらに、SQL ストアード・プロシージャーでは分解対象の XML 文書が複数の XMLTABLE 関数呼び出しで使用される場合でも、構文解析が行われるのは 1 度限りだというパフォーマンス上の利点もあります。




上に戻る


XML 分解の例

ここからは、アノテーション付き XML スキーマ分解と XMLTABLE 分解のそれぞれの方法を使って XML 文書を分解する例を取り上げます。

サンプル XML データ

例えば、メール・メッセージを表す XML データがあるとします。以下は、その典型的な文書の一例です。


リスト 2. メール・メッセージを表すサンプル XML データ
                
<email:mails xmlns:email="http://mymail.com/mails">
   <mail>
	<envelope>
         <from></from>
	   <to></to>
	   <email:Date></email:Date>
	   <subject></subject>
	</envelope>
	<body></body>
	<attachment></attachment>
   </mail>
   <mail>
	...
   </mail>
	...
</email:mails>

それぞれの <mail> メッセージには、エンベロープ、本文、そして添付が含まれます。XML 文書に含められるこの <mail> 要素の数には制限がありません。この例では簡潔にするため、添付はバイナリー・データではなくテキストであるという前提にします。

リレーショナル・スキーマ

多くの場合、分解を実行する際に既存のリレーショナル・スキーマは制御することはできません。例えば 3 つのリレーショナル表があり、これらの表に文書を分解するとします。この 3 つの表の定義は以下のとおりです。


リスト 3. リレーショナル・スキーマの DDL
                
create table envelopext (
docID 		integer not null generated always as identity primary key, 
mailfrom 	varchar(100), 
mailto		varchar(100), 
maildate 	varchar(30), 
subject 	varchar(100)
);

create table bodyxt (
bodyId		integer not null generated always as identity primary key,
body		varchar(30000)
);

create table attachxt (
attachId	integer not null generated always as identity primary key,
attachment	varchar(100)
);




上に戻る


アノテーション付き XML スキーマ分解を使った場合の XML データの分解とリレーショナル表への挿入

最後の前提として、目的とするマッピングによってアノテーションを付けた状態の XML スキーマがあるとします。前述のとおり、マッピングを行うには Data Studio Mapping Editor などの既存のツールを使って自動的にアノテーションを生成すると便利です (完全にアノテーションを付けた状態の XML スキーマのコピーについては、「ダウンロード」セクションを参照してください)。

Java アプリケーションを使用している場合は、JDBC および Java InputStream を使用して DB2 分解ストアード・プロシージャー xdbDecompXML を呼び出すだけで、XML ファイルの内容を直接ストアード・プロシージャーに渡すことができます。リスト 4 では、この方法を使用しています。


リスト 4. xdbDecompXML ストアード・プロシージャーの呼び出し
                
String sql = "{CALL xdbDecompXML(?,?,?,?,?,NULL,NULL,NULL)}";
CallableStatement cstmt = con.prepareCall( sql );

String filename = "mail.xml";
File currFile = new File( filename );
long length = currFile.length();

// SQL Schema Name
// assume NULL
cstmt.setNull( 1, Types.VARCHAR );

// XML Schema Name
cstmt.setString( 2, "\"TEST001\"" );

// XML document to be decomposed, represented as a BLOB
BufferedInputStream bis = 
new BufferedInputStream( new FileInputStream( filename ) );
cstmt.setBinaryStream( 3, bis, ( int ) length );

// XML Document identifier
cstmt.setString( 4, "TEST001" );

// Options to validate the instance document against the XML Schema
int validate = 0;
cstmt.setInt( 5, validate );

/*
The last 3 parameters are reserved for future use.  
Currently NULL values are expected and must be passed in
*/

cstmt.execute();
con.commit();

cstmt.close(); 

アプリケーションに関する限り、上記では標準的なストアード・プロシーアーを呼び出しているだけです。XML スキーマにはすでにアノテーションが付けられて XSR に登録されているので、ストアード・プロシージャーが XML 文書を取得してマッピング先の 3 つの表に分解します。




上に戻る


XMLTABLE 分解を使った場合の XML データの分解とリレーショナル表への挿入

XMLTABLE 分解が同じ操作を実行できることを示すため、同じ XML 文書と一連のリレーショナル表に対して XMLTABLE と SQL INSERT 文の組み合わせを使用します。必ずしも必要なわけではありませんが、XMLTABLE 分解機能は SQL ストアード・プロシージャーの中に組み込みます。アプリケーションの観点からすると、XMLTABLE 分解を使用するということはアノテーション付き XML スキーマ分解とまったく同じく、ストアード・プロシージャーを呼び出すということです。

ストアード・プロシージャーを検討する前に、これを呼び出すための Java コードを作成してください。リスト 5 に、ストアード・プロシージャーの呼び出しを記載します。


リスト 5. XMLTABLE を使用したストアード・プロシージャーの呼び出し
                
// sql stored procedure
String sql = "{CALL XMLTINSERT(?)}";
		
CallableStatement cstmt = con.prepareCall( sql );
String filename = "mail.xml";

File currFile = new File( filename );
long length = currFile.length();
		
BufferedInputStream bis = 
new BufferedInputStream( new FileInputStream( filename ) );

cstmt.setBinaryStream( 1, bis, ( int ) length );
cstmt.execute();
con.commit();
cstmt.close();


このストアード・プロシージャーは XML 型の 1 つのパラメーターを持つように定義されています。それ以外の点では xdbDecompXML の呼び出しと非常によく似ていて、この場合も、Java InputStream は XML ファイルの内容をストアード・プロシージャーに直接渡すように定義されています。

上記の例に対する XMLTABLE 文を使用した SQL ストアード・プロシージャーはリスト 6 のとおりです。


リスト 6. XMLTABLE 分解を使用したストアード・プロシージャー
                
CREATE PROCEDURE XMLTINSERT (IN db2xml XML)
	SPECIFIC XMLTINSERT
------------------------------------------------------------------------
-- SQL Stored Procedure 
-- db2xml is an IN parameter of type XML 
------------------------------------------------------------------------
P1: BEGIN

-- TABLE ENVELOPEXT
INSERT INTO ENVELOPEXT (MAILFROM, MAILTO, MAILDATE, SUBJECT)
SELECT MAILFROM, MAILTO, MAILDATE, SUBJECT
FROM
XMLTABLE(XMLNAMESPACES(
'http://www.sal.com/mails' AS "email"),
'$doc/email:mails/mail'
PASSING  DB2XML AS "doc" 
	COLUMNS 
MAILFROM 	VARCHAR (100)	PATH 'envelope/from',
MAILTO 		VARCHAR (100) 	PATH 'envelope/to',
MAILDATE 	VARCHAR (30) 	PATH 'envelope/email:Date',
SUBJECT 	VARCHAR (100) 	PATH 'envelope/Subject') AS T;
	    
-- TABLE BODYXT
INSERT INTO BODYXT (BODY)
SELECT BODY
FROM
XMLTABLE(XMLNAMESPACES(
'http://www.sal.com/mails' AS "email"),
'$doc/email:mails/mail'
PASSING  DB2XML AS "doc" 
	COLUMNS 
BODY 		VARCHAR (30000)	PATH 'body') AS T;
	
-- TABLE ATTACHXT
INSERT INTO ATTACHXT (ATTACHMENT)
SELECT ATTACHMENT
FROM
XMLTABLE(XMLNAMESPACES(
'http://www.sal.com/mails' AS "email"),
'$doc/email:mails/mail'
PASSING  DB2XML AS "doc" 
	COLUMNS 
ATTACHMENT 	VARCHAR (100) PATH 'attachment/@email:name') AS T;

END P1%


個別の INSERT 文が 3 つあることに注目してください。その理由は、表は 3 つあり、それぞれの表に対して個別の XMLTABLE 文を呼び出さなければならないためです。以下に、最初の INSERT 文について部分ごとに説明します。

上記は標準的な INSERT 構文です。この構文では ENVELOPEXT 表の MAILFROM、MAILTO、MAILDATE、SUBJECT の各列に挿入することになります。次に、INSERT のソースが続きます。

挿入データは SELECT 文の実行結果をソースとします。この場合、MAILFROM、MAILTO、MAILDATE、および SUBJECT 列を取得することになります。ここからがいよいよ興味深い部分です。SELECT のデータは XMLTABLE 関数の結果によってもたらされます。

XMLTABLE(XMLNAMESPACES(
'http://www.sal.com/mails' AS "email"),
'$doc/email:mails/mail'
PASSING  DB2XML AS "doc"

XMLTABLE は XQuery 式をパラメーターと見なします。この例での XQUERY 式は以下のとおりです。

'$doc/email:mails/mail'

上記についてはこの後すぐに説明しますが、まずは XML データのソースを見てください。

PASSING  DB2XML AS "doc" 

DB2XML は XML ソースを提供します。この場合の DB2XML はストアード・プロシージャーの IN パラメーターで、つまり XML 値となります。XQuery 式が評価されると、XQuery 変数は渡された内容と同じ値 (DB2XML)、そして AS 節で指定された名前 (doc) で表されます。したがって、'$doc/email:mails/mail' はこのパスで定義された要素のシーケンスを XML 文書内で参照することになります。

最後に指摘しておかなければならない点として、パスには名前空間が含まれていることに着目してください。DB2 には名前空間の参照先を指示しなければなりませんが、そのために使用できるのが XMLNAMESPACES 関数です。

XMLNAMESPACES('http://www.sal.com/mails' AS "email")

XMLNAMESPACES 関数は XMLTABLE で使用される XQuery 式の静的コンテキストに名前空間を提供するため、さまざまな XQuery 式が名前空間宣言を組み込んだり、そのプロローグで名前空間宣言を繰り返したりする必要がなくなります。名前空間を XQuery プロローグで宣言することは可能ですが、XQuery プロローグでの名前空間宣言と比べ、XMLNAMESPACES を使うと XMLTABLE の引数に含まれるすべての XQuery 式で名前空間を使用できるため、コードを繰り返さなくても済むという利点があります。

表関数は表の列を返します。これらの列を定義するには、COLUMNS 節を使用します。

	COLUMNS 
MAILFROM 	VARCHAR (100)	PATH 'envelope/from',
MAILTO 		VARCHAR (100) 	PATH 'envelope/to',
MAILDATE 	VARCHAR (30) 	PATH 'envelope/email:Date',
SUBJECT 	VARCHAR (100) 	PATH 'envelope/Subject') AS T;

それぞれの PATH 節も XQuery 式ですが、その対象は XML 文書全体ではなく、XML ソース節に定義されたコンテキスト ($doc/email:mails/mail) です。つまり、パス envelope/From は <mail> 要素からのパスということになります。MAILFROM 節は VARCHAR(100) になるように定義され、そのコンテンツは完全 XML パス $doc/email:mails/mail/envelope/from から取得されます。上記以外の列にも同じような方法でデータが設定されます。

XMLTABLE の結果はENVELOPEXT 表に挿入されます。他の 2 つの XMLTABLE 文も同じように BODYXT 表、ATTACHXT 表にそれぞれ結果を挿入します。また、実行される XMLTABLE 文は 3 つありますが、XML 文書はストアード・プロシージャーの変数であるため、構文解析は 1 度しか行われません。

最後に、元の XML 文書がどのような内容だったかを思い出してください。XMLTABLE 文は <mail> 要素ごとに 1 つの行を返します。<mail> 要素は複数存在する可能性もあるため、ストアード・プロシージャーを 1 度呼び出すと表内に行が多数作成される場合もあります。つまり、<mail> 要素が 20 あるとすると、ストアード・プロシージャーは 20 の行を挿入するということです。

ストアード・プロシージャーが xtinsert.db2 というファイルに保管されている場合、ストアード・プロシージャーを DB2 に作成するには、以下のコマンドを CLP 上で自分で実行するか、または DB2 管理者に実行してもらってください。これで、アプリケーションがストアード・プロシージャーを使えるようになります。

db2 -td% -vf xtinsert.db2




上に戻る


XML 分解の特殊な事例

ここからは、アノテーション付き XML スキーマでは容易に分解できない、いくつかの XML 文書について説明します。これらの特殊な事例は、XQuery 式を実行エンジンとする XMLTABLE 分解を使えば、プログラムによってマッピングすることができます。

XBRL データによる子要素間の多対多関係のマッピング

技術的な観点から、XBRL (eXtensible Business Reporting Language) データが要素間の関係を定義する方法は注目に値します。これらの関係が表すのは、実世界のビジネス・プロセスです。

以下のリスト 7 に記載する単純な XBRL 文書を見てください。


リスト 7. サンプル XBRL データ
                
<?xml version="1.0" encoding="utf-8"?>
<linkbase 
   xmlns="http://www.xbrl.org/2003/linkbase" 
   xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
   xmlns:xlink="http://www.w3.org/1999/xlink" 
   xsi:schemaLocation="http://www.xbrl.org/2003/linkbase xbrl-linkbase-2003-12-31.xsd">
                                                     
  <calculationLink 
	xlink:type="extended" 
	xlink:role=http://www.xbrl.org/2003/role/link 
	xlink:title="Calculations, All">

    <loc 
	xlink:type="locator" 
	xlink:href="BasicCalculation.xsd#ci_TotalPropertyPlantEquipment" 
	xlink:label="ci_TotalPropertyPlantEquipment" />

    <loc 
	xlink:type="locator" 
	xlink:href="BasicCalculation.xsd#ci_Land" 
	xlink:label="ci_Land" />

    <loc 
	xlink:type="locator" 
	xlink:href="BasicCalculation.xsd#ci_Building" 
	xlink:label="ci_Building" />

    <loc 
	xlink:type="locator" 
	xlink:href="BasicCalculation.xsd#ci_FurnitureFixtures" 
	xlink:label="ci_FurnitureFixtures" />

    <loc 
	xlink:type="locator" 
	xlink:href="BasicCalculation.xsd#ci_ComputerEquipment" 
	xlink:label="ci_ComputerEquipment" />

    <loc 
	xlink:type="locator" 
	xlink:href="BasicCalculation.xsd#ci_Other" 
	xlink:label="ci_Other" />

    <calculationArc 
	xlink:type="arc" 
	xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item" 
	xlink:from="ci_TotalPropertyPlantEquipment" 
	xlink:to="ci_Land" order="1" weight="1" use="optional" />

    <calculationArc 
	xlink:type="arc" 
	xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item" 
	xlink:from="ci_TotalPropertyPlantEquipment" 
	xlink:to="ci_Building" order="2" weight="1" use="optional" />

    <calculationArc 
	xlink:type="arc" 
	xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item" 
	xlink:from="ci_TotalPropertyPlantEquipment" 
	xlink:to="ci_FurnitureFixtures" order="3" weight="1" use="optional" />

    <calculationArc 
	xlink:type="arc" 
	xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item" 
	xlink:from="ci_TotalPropertyPlantEquipment" 
	xlink:to="ci_ComputerEquipment" order="4" weight="1" use="optional" />

    <calculationArc 
	xlink:type="arc" 
	xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item" 
	xlink:from="ci_TotalPropertyPlantEquipment" 
	xlink:to="ci_Other" order="5" weight="1" use="optional" />

  </calculationLink>
</linkbase>


XBRL: eXtensible Business Reporting Language
XBRL とはビジネス・データおよび財務データを電子的にやり取りするための XML 言語で、新興のオープン・スタンダードとして主に財務情報の収集およびレポートを行うために使用されています。XBRL では項目間の相互関係を示すことができるため、それぞれの財務項目がどのように計算されるか、そして編成あるいは表示目的で特定のグループに分類されるかどうかを表すことができます。詳細は、この記事の「参考文献」セクションを参照してください。

XBRL はさらにセマンティクスを追加して XML の機能を強化します。この言語による重要な機能強化の 1 つとして挙げられるのは、「アーク (arc)」による 2 つの項目の関連付けです。上記の文書でこれに相当するのは <calculationArc> 要素です、この要素は 2 つのアセット間の関係を定義します。「arcrole」属性は URI に基づき、この特定のアークが「to」属性と「from」属性の総和関係であることを示します。それぞれの「to」属性が合計される個別の項目、例えば「ci_Land」、「ci_Building」などを識別します。これらの項目が合計されて「from」属性のコスト (上記の例では「ci_TotalPropertyPlantEquipment」) になります。

「ci_Land」、「ci_Building」などの属性は、実際にはラベルです。各ラベルが表す対象を識別するには、<loc> 要素を使用します。例えば以下の <loc> 要素を見ると、その「label」属性は「ci_Land」に設定されています。

<loc 
	xlink:type="locator" 
	xlink:href="BasicCalculation.xsd#ci_Land" 
	xlink:label="ci_Land" />

上記には、「BasicCalculation.xsd」という XML スキーマ文書を指す「href」属性があります。この文書を検索すると、「ci_land」の実際の値が見つかります。

XBRL データの詳細な分析はこの記事では行いませんが、この XML 文書を「from」および「to」属性を保管する「ARC」表に分解すればいいことは想像できるはずです。ただし、この場合に必要なのはラベルではなく、実際の値を提供する参照の名前です。

「ARC」表には自動的に生成された 3 つの列、ARCID、ARCFROM、ARCTO があります (リスト 8 を参照)。


リスト 8. ARC 表の DDL
                
CREATE TABLE ARC (
  ARCID		integer not null generated always as identity primary key,
  ARCFROM	varchar(100),
  ARCTO		varchar(100)
);

分解の際には、<calculationArc> 要素の「from」および「to」属性の値が <loc> 要素の該当する「href」属性に置き換えられます。その一例として、以下に要素を示します。

<calculationArc 
	xlink:type="arc" 
	xlink:arcrole="http://www.xbrl.org/2003/arcrole/summation-item" 
	xlink:from="ci_TotalPropertyPlantEquipment" 
	xlink:to="ci_Land" order="1" weight="1" use="optional" />

<loc> 要素の 2 つの値、BasicCalculation.xsd#ci_TotalPropertyPlantEquipmentBasicCalculation.xsd#ci_Land は、ARC 表の ARCFROM 列と ARCTO 列にそれぞれ挿入されます。この 2 つの値は <calculationArc> 要素の from="ci_TotalPropertyPlantEquipment" ラベルと to="ci_Land" ラベルに対応します。表に含まれる他の行にも同じような方法でデータが設定されます。

アノテーション付き XML スキーマ分解では、このように条件付きで動的な値に基づいて行を構成する複数の子要素の多対多のマッピングを分解することができません。そこで一役買うのが XMLTABLE です。前にも説明したように、XMLTABLE 関数は XQuery を実行エンジンとしているため、非常に強力なツールとなっています。

リスト 9 は、必要に応じて分解を行うストアード・プロシージャーです。


リスト 9. XMLTABLE による XBRL 分解のための SQL ストアード・プロシージャー
                
CREATE PROCEDURE XMLTINSERT2 ( IN db2xml XML )
	SPECIFIC XMLTINSERT2
------------------------------------------------------------------------
-- SQL Stored Procedure 
-- db2xml 
------------------------------------------------------------------------
P1: BEGIN
INSERT INTO ARC
	(ARCFROM,
	ARCTO) 
SELECT	
	ARCFROM,
	ARCTO 
	FROM XMLTABLE(
	'$doc/*:linkbase/*:calculationLink/*:calculationArc' 
		PASSING DB2XML AS "doc"
		COLUMNS
ARCFROM VARCHAR(100) PATH 'let $x := . return $x/../*:loc[@*:label=$x/@*:from]/@*:href',
ARCTO 	VARCHAR(100) PATH 'let $x := . return $x/../*:loc[@*:label=$x/@*:to]/@*:href'
	)AS T;	
END P1%


まず、以下の XQuery 式を使ってコンテキストが <calculationArc> 要素になるように選択します。

'$doc/*:linkbase/*:calculationLink/*:calculationArc'

元の XBRL 文書にはさまざまな名前空間が含まれていますが、XQuery 式ではこれらの名前空間は関係ないので、名前空間にはワイルド・カードとしてアスタリスク (*) を使います。ワイルド・カードの使用は、名前空間が異なる複数の <calculationArc> 要素がある場合には問題になるかもしれませんが、この場合には該当しません。

必要なものはすべてワイルド・カードを使用した表現を利用して取得することができます。例えば COLUMNS 節が定義する PATH を見てください。ARCFROM を取得するには、現行の計算の「from」属性と一致する「label」属性を持つ要素が必要です。これをテストするため、XQuery キーワードの let を使って現行のテキスト・ノードを変数 $x に割り当てます。最後に現行のコンテキストからナビゲートして <loc> 要素まで戻り、「label」属性と「from」属性が一致する「href」属性を返します。

'let $x := . return $x/../*:loc[@*:label=$x/@*:from]/@*:href'

ARCTO についても同じように値を取得します。表 1 に、ストアード・プロシージャーを呼び出した後に分解された表内のデータを記載します。


表 1. ARC 表内の分解されたデータ
ARCIDARCFROMARCTO
1BasicCalculation.xsd#ci_TotalPropertyPlantEquipmentBasicCalculation.xsd#ci_Land
2BasicCalculation.xsd#ci_TotalPropertyPlantEquipmentBasicCalculation.xsd#ci_Building
3BasicCalculation.xsd#ci_TotalPropertyPlantEquipmentBasicCalculation.xsd#ci_FurnitureFixtures
4BasicCalculation.xsd#ci_TotalPropertyPlantEquipmentBasicCalculation.xsd#ci_ComputerEquipment
5BasicCalculation.xsd#ci_TotalPropertyPlantEquipmentBasicCalculation.xsd#ci_Other

再帰要素を持つ XML 文書

今度は別の例として、リスト 10 の XML 文書を見てください。これは産業界でよく見かける一般的なタイプの XML 文書です。


リスト 10. 部品表を表す XML 文書
                
<?xml version="1.0" encoding="UTF-8"?>
<items>
   <item desc="computersystem" model="L1234123">
	  <part desc="computer" partnum="5423452345">
		<part desc="motherboard" partnum="5423452345">
			<part desc="CPU" partnum="6109486697">
				<part desc="register" partnum="6109486697"/>
			</part>
			<part desc="memory" partnum="545454232">
				<part desc="transistor" partnum="6109486697"/>
			</part>
		</part>
		
		<part desc="diskdrive" partnum="6345634563456">
			<part desc="spindlemotor" partnum="191986123"/>
		</part>
		<part desc="powersupply" partnum="098765343">
			<part desc="powercord" partnum="191986123"/>
		</part>
	  </part>
	
	  <part desc="monitor" partnum="898234234">
		<part desc="cathoderaytube" partnum="191986123"/>
	  </part>
	
	  <part desc="keyboard" partnum="191986123">
		<part desc="keycaps" partnum="191986123"/>
	  </part>
	
	  <part desc="mouse" partnum="98798734">
		<part desc="mouseball" partnum="98798734"/>
	  </part>
   </item>
</items>

このようなタイプの XML 文書は一般的に「部品表」と呼ばれています。サンプル文書には 1 つの項目しか含まれていませんが、部品表には無数の項目を含めることができます。この文書で興味深い点は、<part> 要素が再帰的であることです。<item> 要素には <part> 子要素が含まれ、その子要素にはさらに <part> 子要素が含まれるなど、子要素が無限にネストされる場合があります。

この文書を、ITEMNAME、PART、および PARENT 列を持つ ITEM 表に分解します。


リスト 11. ITEM 表の DDL
                
CREATE TABLE ITEM (
  PID		integer not null generated always as identity primary key,
  ITEMNAME	varchar(25),
  PART		varchar(25),
  PARENT	varchar(25)
);


アノテーション付き XML スキーマ分解では、XML スキーマで再帰要素の定義を使用することはできません。この問題を解決するために使用するのは、やはり XMLTABLE 分解です。リスト 12 に XMLTABLE 分解を使用したストアード・プロシージャーを記載します。


リスト 12. 部品表を分解するための SQL ストアード・プロシージャー
                
CREATE PROCEDURE XMLTINSERT3 ( IN db2xml XML )
	SPECIFIC XMLTINSERT3
------------------------------------------------------------------------
-- SQL Stored Procedure 
-- db2xml 
------------------------------------------------------------------------
P1: BEGIN
INSERT INTO ITEM
	(ITEMNAME,
	PART,
	PARENT) 
SELECT 	
	A.ITEMNAME,
	B.PART,
	B.PARENT
	FROM 
	XMLTABLE('$doc/items/item' PASSING DB2XML AS "doc"
	COLUMNS
		ITEMNAME 	VARCHAR(25)	PATH './@desc',
		ITEM		XML			PATH '.'
	)AS A,
	XMLTABLE('$doc//part' PASSING A.ITEM AS "doc"
	COLUMNS
		PART 		VARCHAR(30) PATH './@desc',
		PARENT		VARCHAR(35) PATH '../@desc'
	)AS B;	
END P1%


この例では、INSERT 文にはソースとして 2 つの XMLTABLE 文があります。最初の XMLTABLE 文では $doc/items/item のコンテキスト・ノードを使って項目の名前を提供しています。さらに、この文は 2 番目の XMLTABLE 文で使用する item というサブツリーを取得します。

2 番目の XMLTABLE 文に含まれている XQuery 式は、現行の <item> サブツリー (A.ITEM) 内から ($doc//part) の条件を満たすすべての <part> 要素を選択します。

これですべての <part> 要素が揃ったので、現行のノード記述を取得して親の記述までナビゲートして戻り、その親の記述を取得します。表 2 に、サンプル・データでストアード・プロシージャーを呼び出した後に ITEM 表に含まれる内容を記載します。


表 2. ITEM 表内の分解されたデータ
ITEMIDITEMNAMEPARTPARENT
1computersystemcomputercomputersystem
2computersystemmotherboardcomputer
3computersystemCPUmotherboard
4computersystemregisterCPU
5computersystemmemorymotherboard
6computersystemtransistormemory
7computersystemdiskdrivecomputer
8computersystemspindlemotordiskdrive
9computersystempowersupplycomputer
10computersystempowercordpowersupply
11computersystemmonitorcomputersystem
12computersystemcathoderaytubemonitor
13computersystemkeyboardcomputersystem
14computersystemkeycapskeyboard
15computersystemmousecomputersystem
16computersystemmouseballmouse

PARENT 列を調べれば、部品の階層を簡単に辿ることができます。例えば、「register」という部品の行 4 で親をたどると「CPU」に行き着きます。「CPU」の親は「motherboard」で、「motherboard」の親は「computer」です。そして「computer」の親は最上位レベルの項目、「computersystem」となっています。




上に戻る


パフォーマンス

FpML: Financial products Markup Language
FpML は、複雑な金融商品を取引するための業界標準仕様です。FpML は店頭市場 (OTC) の金融デリバティブ取引を表します。その価格は他のアセットから引き出され、(公開取引によってではなく) 関係者間で相互に取り引きされます。このような取引は今日の金融市場でかなりの部分を占めていますが、大きなリスクを抱えているため、取引に関わる企業が技術投資を行うための資本源として極めて重要なものになっています。

このパフォーマンスの比較で用いられている例は、2005年7月14日にリリースされた FpML 4.1 Recommendation Specification をベースとしています。詳細は、「参考文献」セクションを参照してください。

パフォーマンスについての徹底した調査はまだ行われていませんが、非公式な調査では、アノテーション付き XML スキーマ分解と XMLTABLE 分解のパフォーマンスはどちらも同じように優れていることが示されています。このセクションでは、私たちが行った非公式な調査による結果をいくつか抜粋して紹介します。

単純なマッピング

分解は、メッセージのコンテンツ・モデルを定義する高度な専用 FpML XML スキーマを使用して行いました。メッセージは FpML 取引をラップします。この XML スキーマは 23 の文書からなり、合計サイズは約 871KB です。12 の共通項目が 1 つの表の中の 12 のリレーショナル列にマッピングされています。この場合、少数のリレーショナル列にマッピングするだけであれば、アノテーション付き XML スキーマ分解と XMLTABLE 分解のパフォーマンスにはほとんど違いがありませんでした。

複雑なマッピング

カスタマーから提供された独自のアノテーション付き XML スキーマを使用したテストも行いました。XML スキーマは 1 つの文書に定義され、そのサイズは約 142KB です。1 つの XML インスタンス文書が 21 の表に分解され、これらの表のリレーショナル列を合計すると数百という数になります。要素によって、複数の行を挿入する結果となるものもあれば、1 つの行しか生成しないものもありました。この場合、アノテーション付き XML スキーマ分解の速度は XMLTABLE 分解に比べ、約 40 パーセント向上するという結果になりました。

考慮事項

XMLTABLE はデータを設定する表ごとに呼び出さなければならないため、表の数が多い場合にはコストがかかります。また、アノテーション付き XML スキーマ分解は XML 文書を 1 度しかトラバースしませんが、XMLTABLE の呼び出しには毎回、文書のトラバースが必要になります。この場合に役立つのが、ストアード・プロシージャーを使用した XMLTABLE 分解です。この方法で分解を実行すれば、XMLTABLE を何度も呼び出すとしても XML 値は 1 度しか構文解析されません。解析された XML 値はそのストアード・プロシージャー呼び出しが有効な間、トラバースが行われるごとに再使用されます。

最後に断っておきますが、ここで紹介した内容はパフォーマンスに関する正式な結果ではありません。厳格なベンチマークのためには、もっとしっかり管理された環境でさらに詳細なパフォーマンス調査を行うことをお勧めします。詳細な調査を行うことにより、単純なものから複雑なものまで、XML スキーマあるいはリレーショナル・スキーマのしきい値を、よりきめ細かいレベルで定義することができます。制御対象として提案する変数は、XML スキーマのサイズ (範囲と深さの両方)、分解に使用する表の数、そして表ごとに含まれる列の数です。




上に戻る


アノテーション付き XML スキーマ分解と XMLTABLE 分解のベスト・プラクティス

この記事では、アノテーション付き XML スキーマ分解と XMLTABLE 分解とでは、異なる方法で XML 文書をリレーショナル表に分解することを説明しました。それぞれのアプリケーションにどちらの方法を採用するかを決める際には、以下の事項を考慮してください。

インスタンス文書と XML スキーマ

分解を実行する際の考慮事項として第一に明らかなことは、XMLTABLE 分解はインスタンス文書で動作するため、XML スキーマは必要ないという点です。アノテーション付き XML スキーマ分解の場合には、マッピングを XML スキーマの一部として定義しなければなりません。

マッピングの変更

アノテーション付き XML スキーマ分解は、XSR に保管されたアノテーション付き XML スキーマに基づいて動作します。そのためマッピングが変更された場合には、XML スキーマを変更し、XSR に再登録する必要がありますが、この作業は Data Studio を使用すれば簡単に行えます。

XMLTABLE 分解は XQuery 式を使用してマッピングを作成します。そのためマッピングが変更されると、すべての XQuery 式を手作業で変更しなければならなくなります。ただし上記の例のようにストアード・プロシージャーに定義されていれば、マッピングが変更されたとしてもストアード・プロシージャーを破棄して再作成するだけで済みます。

マッピング定義の柔軟性

アノテーション付き XML スキーマ分解のマッピングは、アノテーションによって定義されます。マッピングは XML スキーマ文書の一部であるため、XML スキーマ言語の範囲および制約に従わなければなりません。XML スキーマ言語が特定の構文を許容しない場合には、この関係をアノテーション付き XML スキーマでマッピングすることは不可能です。ただし、許容されるさまざまなマッピングに関しては、ツールを使うことでマッピング・アノテーションの作成が容易になり、しかも自動化されます。さらに、複雑な XML スキーマでも簡単に複数の表にマッピングすることができます。

XMLTABLE 分解を使用すると、INSERT 文で列に設定するデータをさまざまなソースから取得することができます。しかも、データの取得は 1 回の XMLTABLE 呼び出しに限られません。また XQuery の機能を利用すると開発者は複雑な式を作成できるため、極めて柔軟にマッピングを定義することができます。この柔軟性を制限するものは、開発者の想像力だけです。それと同時に、この柔軟性によって複雑さが増すことになるため、開発者がXQuery 言語を十分に理解していない場合には、柔軟性を生かせるようになるまでに学習曲線に従った時間が必要になるかもしれません。最後にもう 1 つ付け加えると、マッピングに多数の表と列が関わっている場合、XMLTABLE 文は厄介になる可能性があります。




上に戻る


まとめ

結局のところ、アノテーション付き XML スキーマ分解と XMLTABLE 分解はどちらも非常に強力なツールであり、どちらを使用するかはユーザーの好みに委ねられることになります。ただし以下のように、一方が他方より推奨される場合もあります。

スキーマが複雑で、マッピングに多数の表が必要な場合には、アノテーション付き XML スキーマ分解を使用してください。使用可能なツールとパフォーマンス上の考慮事項の点から、この方法が賢い選択となります。この記事では説明しませんでしたが、アノテーション付き XML スキーマ分解では XML の内容に基づいた条件付きの分解や、XML の内容をどのように変換するか指定してから挿入するなどの拡張機能も使用することができます。XMLTABLE 分解にもこのようなサポート機能はありますが、アノテーションを使えば XML スキーマ内で同じことをより簡単に行えます。

一方、XML スキーマが存在しない場合、あるいは特殊な用途のため柔軟性が必要とされる場合には XMLTABLE 分解を使用してください。例えば、複数の子要素間で多対多のマッピングを行い、条件付きで動的な値に応じて行を生成する場合、再帰的な要素をマッピングする場合、あるいはINSERT 文の構成方法を厳密に制御したい場合などには、XMLTABLE 分解が最適な方法となります。

この記事では、アノテーション付き XML スキーマ分解の代替手段として XMLTABLE 分解を使用して XML 文書をリレーショナル表に分解する方法を説明しました。また、それぞれの使用方法についての推奨案とベスト・プラクティスも紹介しました。いずれも DB2 における pureXML 技術の一環であるこの 2 つの分解方法は、開発者と管理者がそれぞれに最善の方法でデータを管理する上で役立つはずです。

謝辞

この記事に関する提案、そして意見を下さった IBM SVL (Silicon Valley Lab) の DB2 pureXML 開発チーム・メンバーの Seeling Cheung、Dung Nguyen、Mayank Pradhan、David Salinero、Cynthia Saracco の各氏に感謝いたします。





上に戻る


ダウンロード

内容ファイル名サイズダウンロード形式
Scripts to create and register objectsmail.zip3KBHTTP
Scripts to create the XBRL examplemany-to-many.zip2KBHTTP
Scripts to create BOM examplerecursive.zip2KBHTTP
ダウンロード形式について


参考文献

学ぶために
  • The DB2 XML Technical Enablement Wiki: DB2 の XML 技術について最新情報を入手してください。ここには XML データの管理、保管、クエリーに対する DB2 のサポートを学ぶためのチュートリアルや参考記事、そしてその他の資料へのリンクが豊富に掲載されています。

  • SQL を使った DB2 XML データの照会」(developerWorks、2006年3月): SQL/XML パブリッシング関数の概要、そして DB2 で XML データをクエリーするための情報が記載されています。

  • DB2 Version 9 for Linux, UNIX, and Windows XML ガイド: 第 10 章「アノテーション付き XML スキーマ分解」を参照してください。

  • From DAD to Annotated XML Schema Decomposition」(developerWorks、2006年4月): XML Extender 分解からアノテーション付き XML スキーマ分解に移行してください。

  • Develop Java applications for DB2 XML data」(developerWorks、2006年5月): ストアード・プロシージャーの呼び出しを含め、Java を使って DB2 から XML データにアクセスしてください。

  • XBRL の詳細を学んでください。

  • FpML の詳細を学んでください。

  • テクノロジーのブックストアで、この記事で取り上げた技術やその他の技術に関する本を探してください。


議論するために


著者について

Salvador は、2002年からカリフォルニア州サンノゼの IBM Silicon Valley Labs で働いています。現在は、DB2 pureXML を含め、IBM のデータ・サーバー製品を対象としたランタイムおよびツール技術に取り組んでいます。


Bert は 2001年に IBM に入社し、DB2 での XML プロジェクトに初期のアーキテクトの 1 人として参加しました。IBM に入社する前に務めていた新興企業、Propel では、スケーラブルな e-commerce アプリケーションをホストする無停止分散ミドルウェアの設計および実装にリーダーとして携わっていました。それ以前は長年 Tandem Computers に勤め、金融業界での多数の重大なアプリケーションを実行するデータベース、NonStop SQL に取り組んできました。




記事の評価


サイト改善のため、ご意見をお寄せください。こちらのフォームからお願いいたします。



はいいいえわからない
 


 


12345
不充分・不完全である大変素晴らしい
 


この記事を共有する

はてなブックマーク はてなブックマーク livedoorクリップ livedoorクリップ del.icio.us del.icio.us Buzzurl(バザール) Buzzurl(バザール) Choix! Choix!
Saafブックマーク Saafブックマーク FC2ブックマーク FC2ブックマーク MM/memo MM/memo ニフティクリップ ニフティクリップ Yahoo!ブックマーク Yahoo!ブックマーク
CZブックマーク CZブックマーク newsing newsing




上に戻る


    日本IBMについて プライバシー お問い合わせ