XML 構文解析

XML 構文解析は、XML データをシリアライズされたストリング形式から階層形式に変換する処理です。

Db2® データベース・サーバーが暗黙的に構文解析を実行するようにすることも、XML 構文解析を明示的に実行することもできます。

暗黙的な XML 構文解析 は、以下の場合に生じます。
  • タイプ XML のホスト変数を使用してデータをデータベース・サーバーに渡すとき、またはタイプ XML のパラメーター・マーカーを使用するとき。

    データベース・サーバーが、ステートメント処理で使用するためにホスト変数またはパラメーター・マーカーの値をバインドするときに、構文解析を行います。

    この場合、暗黙的な構文解析を使用する必要があります。

  • INSERT、UPDATE、DELETE、または MERGE ステートメントで、 ストリング・データ・タイプ (文字、グラフィック、またはバイナリー) のホスト変数、パラメーター・マーカー、 または SQL 式を XML 列に割り当てるとき。 SQL コンパイラーが XMLPARSE 関数をステートメントに暗黙的に追加するとき、構文解析が生じます。

明示的な XML 構文解析 は、XMLPARSE 関数を入力 XML データに対して呼び出すことによって実行します。 XMLPARSE の結果は、XML データ・タイプを受け入れるすべてのコンテキストで使用できます。 例えば、その結果を XML 列に割り当てること、またはタイプ XML のストアード・プロシージャー・パラメーターとして使用することができます。

XMLPARSE 関数は、非 XML の文字またはバイナリー・データ・タイプを入力とします。 組み込み動的 SQL アプリケーションでは、XMLPARSE の入力文書を表すパラメーター・マーカーを 適切なデータ・タイプにキャストする必要があります。 以下に例を示します。
INSERT INTO MyCustomer (Cid, Info) 
 VALUES (?, xmlparse(document cast(? as clob(1k)) preserve whitespace))

組み込み静的 SQL アプリケーションでは、XMLPARSE 関数のホスト変数引数を XML タイプ (XML AS BLOB、XML AS CLOB、XML AS DBCLOB タイプ) として宣言することはできません。

XML 構文解析および空白処理

暗黙的または明示的な XML 構文解析中、データをデータベースに保管するときに、境界空白文字の保存または除去を制御できます。

XML 標準によれば、空白文字とは、読みやすさを促進するために文書中に置かれたスペース文字 (U+0020)、復帰 (U+000D)、改行 (U+000A)、またはタブ (U+0009) のことを指します。 これらの記号がテキスト・ストリングの一部として出現する場合には、それは空白文字としては扱われません。

境界空白 は、要素と要素の間にある空白文字です。 例えば、次の文書で、<a><b> との間のスペース、 および </b></a> との間のスペースは、境界空白です。
<a> <b> and between </b> </a>

XMLPARSE を明示的に呼び出すとき、STRIP WHITESPACE または PRESERVE WHITESPACE オプションを使用して 境界空白の保存を制御します。 デフォルトでは、境界空白は除去されます。

暗黙的な XML 構文解析の場合:
  • 入力データ・タイプが XML タイプではないか、または XML データ・タイプにキャストされていない場合、Db2 データベース・サーバーは常に空白を除去します。
  • 入力データ・タイプが XML データ・タイプの場合、CURRENT IMPLICIT XMLPARSE OPTION 特殊レジスターを使用して境界空白の保存を制御できます。 この特殊レジスターを STRIP WHITESPACE または PRESERVE WHITESPACE に設定できます。 デフォルトでは、境界空白は除去されます。
XML 妥当性検査を使用する場合、以下の状況において、Db2 データベース・サーバーは CURRENT IMPLICIT XMLPARSE OPTION 特殊レジスターを無視し、妥当性検査ルールだけを使用して空白の除去または保存を決めます。
xmlvalidate(? ACCORDING TO XMLSCHEMA ID schemaname)
xmlvalidate(?)
xmlvalidate(:hvxml ACCORDING TO XMLSCHEMA ID schemaname)
xmlvalidate(:hvxml)
xmlvalidate(cast(? as xml) ACCORDING TO XMLSCHEMA ID schemaname)
xmlvalidate(cast(? as xml)) 
上記の例では、? は XML データを表し、:hvxml は XML ホスト変数を表します。

XML 妥当性検査が空白処理にどのように影響するかについては、 XML 妥当性検査 を参照してください。

XML 標準は、XML データ内の空白文字の除去または保存を制御する xml:space 属性を指定しています。 xml:space 属性は、 暗黙的または明示的な XML 構文解析のための空白設定をオーバーライドします。

例えば、以下の文書では、< b> の直前と直後のスペースは、XML 構文解析オプションに関係なく常に保持されます。これは、スペースが属性 xml:space="preserve"を持つノード内にあるためです。
<a xml:space="preserve"> <b> <c>c</c>b </b></a>
ただし、以下の文書では、< b> の直前と直後のスペースを XML 構文解析オプションで制御できます。これは、スペースが属性 xml:space="default"を持つノード内にあるためです。
<a xml:space="default"> <b> <c>c</c>b </b></a>

非 Unicode データベースでの XML の構文解析

XML 文書が非 Unicode データベースに渡される場合、コード・ページ変換が、まず最初に文書がクライアントからターゲット・データベース・サーバーに渡される際に実行され、次に文書が Db2 XML パーサーに渡される際に実行されることがあります。 タイプが XML のホスト変数またはパラメーター・マーカーを使用して XML 文書を渡す場合、コード・ページ変換は実行されません。 文字データ・タイプ (CHAR、VARCHAR、CLOB、または LONG VARCHAR) を使用して XML 文書を渡す場合は、コード・ページ変換の結果として、XML データ中の、ターゲット・データベースのコード・ページの一部でない文字に関する代替文字に置き換わることがあります。

文字データ・タイプを使用して XML データを構文解析する場合に、代替文字に変換されないようにし、挿入される XML データが劣化しないようにするには、ソース文書中のすべてのコード・ポイントをターゲット・データベースのコード・ページの一部にします。 このコード・ページの一部でない文字の場合、正しい Unicode コード・ポイントを指定した 10 進または 16 進文字エンティティー参照を使用できます。 例えば、 &#x003E または &#0062 のいずれかを使用して、> (より大) 符号文字を指定することができます。

ENABLE_XMLCHAR 構成パラメーターを使用して、文字データ・タイプの場合に XML 構文解析を有効にするかどうかも制御できます。 ENABLE_XMLCHAR を「NO」に設定すると、文字データ・タイプの使用時に明示的および暗黙的な XML 構文解析が両方とも実行されないようになります。

XML 構文解析および DTD

入力データが内部文書タイプ宣言 (DTD) を含んでいるかまたは外部 DTD を参照する場合、XML 構文解析処理はそれらの DTD の構文も検査します。 さらに、構文解析処理は以下を行います。
  • 内部および外部 DTD で定義されたデフォルト値を適用する
  • エンティティー参照およびパラメーター・エンティティーを展開する

以下の例は、XML 文書内の空白が様々な状態でどのように扱われるかを示します。

例: ファイル c8.xml には、次の文書が含まれています。
<customerinfo xml:space="preserve" Cid='1008'>
  <name>Kathy Smith</name>
  <addr country='Canada'>
    <street>14 Rosewood</street>
    <city>Toronto</city>
    <prov-state>Ontario</prov-state>
    <pcode-zip>M6W 1E6</pcode-zip>
  </addr>
  <phone type='work'>416-555-3333</phone>
</customerinfo>
JDBC アプリケーションで、ファイルから XML 文書を読み取り、サンプル Customer 表のコピーである表 MYCUSTOMER の XML 列 INFO にそのデータを挿入します。 Db2 データベース・サーバーが、 暗黙的な XML 構文解析操作を実行するようにします。
PreparedStatement insertStmt = null;
String sqls = null;
int cid = 1008;
sqls = "INSERT INTO MyCustomer (Cid, Info) VALUES (?, ?)";
insertStmt = conn.prepareStatement(sqls);
insertStmt.setInt(1, cid);
File file = new File("c8.xml");
insertStmt.setBinaryStream(2, new FileInputStream(file), (int)file.length());
insertStmt.executeUpdate();
空白処理は指定されていないので、通常であれば、デフォルトの動作として空白文字が除去されます。 しかし、文書には xml:space="preserve" 属性が含まれているので、 空白文字は保存されます。 つまり、文書の中の復帰、改行、および要素間のスペースはそのまま残ります。
保管データを取り出した場合、その内容は次のようになります。
<customerinfo xml:space="preserve" Cid='1008'>
  <name>Kathy Smith</name>
  <addr country='Canada'>
    <street>14 Rosewood</street>
    <city>Toronto</city>
    <prov-state>Ontario</prov-state>
    <pcode-zip>M6W 1E6</pcode-zip>
  </addr>
  <phone type='work'>416-555-3333</phone>
</customerinfo>
例: 次の文書が BLOB ホスト変数 blob_hostvar 内にあると想定します。
<customerinfo xml:space="default" Cid='1009'>
  <name>Kathy Smith</name>
  <addr country='Canada'>
    <street>15 Rosewood</street>
    <city>Toronto</city>
    <prov-state>Ontario</prov-state>
    <pcode-zip>M6W 1E6</pcode-zip>
  </addr>
  <phone type='work'>416-555-4444</phone>
</customerinfo>
静的な組み込み C アプリケーションで、文書をホスト変数から表 MyCustomer の XML 列 Info に挿入します。 ホスト変数は XML タイプではないので、XMLPARSE を明示的に実行する必要があります。 境界空白を除去するには、STRIP WHITESPACE を指定します。
EXEC SQL BEGIN DECLARE SECTION;
   SQL TYPE BLOB (10K) blob_hostvar;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL INSERT INTO MyCustomer (Cid, Info) 
  VALUES (1009,
  XMLPARSE(DOCUMENT :blob_hostvar STRIP WHITESPACE));
文書には xml:space="default" 属性が含まれているので、XMLPARSE に指定された STRIP WHITESPACE が空白処理を制御します。 つまり、文書の中の復帰、改行、および要素間のスペースは除去されます。
保管データを取り出した場合、次の内容の単一の行になります。
<customerinfo xml:space="default" Cid='1009'>
<name>Kathy Smith</name><addr country='Canada'><street>15 Rosewood</street>
<city>Toronto</city><prov-state>Ontario</prov-state><pcode-zip>M6W 1E6</pcode-zip>
</addr><phone type='work'>416-555-4444</phone></customerinfo>
例: C 言語アプリケーションで、ホスト変数 clob_hostvar に、内部 DTD を持つ次の文書が含まれています。
<!DOCTYPE prod [<!ELEMENT description (name,details,price,weight)> 
   <!ELEMENT name (#PCDATA)> 
   <!ELEMENT details (#PCDATA)> 
   <!ELEMENT price (#PCDATA)> 
   <!ELEMENT weight (#PCDATA)> 
   <!ENTITY desc  "Anvil">
]>
<product pid=''110-100-01'' >
 <description>
 <name>&desc;</name>
 <details>Very heavy</details>
 <price>         9.99            </price>
 <weight>1 kg</weight>
 </description>
</product>'
サンプルの PRODUCT 表のコピーである表 MYPRODUCT にデータを挿入します。
EXEC SQL BEGIN DECLARE SECTION;
   SQL TYPE CLOB (10K) clob_hostvar;
EXEC SQL END DECLARE SECTION;
...
EXEC SQL insert into 
  Product ( pid, name, Price, PromoPrice, PromoStart, PromoEnd, description ) 
  values ( '110-100-01','Anvil', 9.99, 7.99, '11-02-2004','12-02-2004', 
  XMLPARSE ( DOCUMENT :clob_hostvar STRIP WHITESPACE ));
XMLPARSE は空白の除去を指定しているので、文書内の境界空白は除去されます。 さらに、データベース・サーバーが XMLPARSE を実行するとき、エンティティー参照 &desc; がその値に置き換えられます。
保管データを取り出した場合、次の内容の単一の行になります。
<product pid="110-100-01"><description><name>Anvil
</name><details>Very heavy</details><price>         9.99            </price>
<weight>1 kg</weight></description></product>