ヘッダーをスキップ
Oracle® XML DB開発者ガイド
11gリリース2 (11.2)
B70200-03
  目次へ移動
目次
索引へ移動
索引

前
 
次
 

11 XMLTypeデータの変換および検証

この章では、XSLTスタイル・シートを使用してXMLTypeデータを変換するための、SQL関数およびXMLType APIについて説明します。XMLTypeインスタンスのXML Schemaに対する検証に使用できる関数およびAPIについても説明します。

この章の内容は次のとおりです。

XMLTypeインスタンスの変換

XML文書には構造はありますが形式はありません。XML文書に形式を追加するには、Extensible Stylesheet Language (XSL)を使用できます。XSLはXMLセマンティクスの表示方法を提供します。XML要素をHTMLなどの他のフォーマット言語またはマークアップ言語にマップできます。

Oracle XML DBでは、Oracle DatabaseのXMLType表、列またはビューに格納されているXMLTypeインスタンスまたはXMLデータは、XSLスタイルシートおよびXMLTypeメソッドtransform()を使用して、HTML、XMLおよびその他のマークアップ言語に(フォーマット)変換できます。このプロセスは、W3CのXSLT 1.0勧告に準拠しています。

XMLTypeインスタンスは、次の方法で変換できます。

  • データベースでOracle SQL関数XMLTransform(またはXMLTypeメソッドtransform())を使用する。

  • XSLT Processor for Javaなどの中間層でOracle XML Developer's Kitの変換オプションを使用する。

SQL関数XMLTRANSFORMおよびXMLTypeメソッドTRANSFORM()

図11-1に、Oracle SQL関数XMLtransformの構文を示します。この関数は引数としてXMLTypeインスタンスとXSLTスタイルシートを受け取ります。スタイルシートはXMLTypeインスタンスまたはVARCHAR2文字列リテラルのいずれかです。スタイルシートをインスタンスに適用し、XMLTypeインスタンスを戻します。

図11-1 XMLTRANSFORMの構文

図11-1の説明が続きます
「図11-1 XMLTRANSFORMの構文」の説明

Oracle SQL関数XMLtransformのかわりにXMLTypeメソッドtransform()を使用することもできます。どちらも機能は同じです。

図11-2に、XSLTスタイルシートを使用してXMLtransformがXML文書を変換する方法を示します。XSLTスタイルシートで指定したように、処理された出力をXML、HTMLなどで戻します。データベース内にXMLTypeとして格納されたXML文書の取得または生成時は、通常はXMLtransformを使用します。

図11-2 XMLTRANSFORMの使用

図11-2の説明が続きます
「図11-2 XMLTRANSFORMの使用」の説明

XMLTRANSFORMおよびXMLType.transform()の例

この項では、Oracle SQL関数XMLtransformおよびXMLTypeメソッドtransform()を使用して、XMLTypeとして格納されているXMLデータを様々な形式に変換する方法について説明します。

例11-1では、この章の他の例を実行するために必要なXML Schemaおよび表を設定します。ここに示したdeleteSchemaのコールは、XML Schemaの作成前に既存のスキーマがないようにするためのものです。そのようなスキーマが存在しない場合は、deleteSchemaでエラーが発生します。

例11-1 XML Schemaの登録およびXMLデータの挿入

BEGIN
  -- Delete the schema, if it already exists.
  DBMS_XMLSCHEMA.deleteSchema('http://www.example.com/schemas/ipo.xsd',4);
END;
/
BEGIN
  -- Register the schema
  DBMS_XMLSCHEMA.registerSchema(
    SCHEMAURL => 'http://www.example.com/schemas/ipo.xsd',
    SCHEMADOC => '<schema targetNamespace="http://www.example.com/IPO"
                          xmlns="http://www.w3.org/2001/XMLSchema"
                          xmlns:ipo="http://www.example.com/IPO">
                    <!-- annotation>
                      <documentation xml:lang="en">
                       International Purchase order schema for Example.com
                       Copyright 2000 Example.com. All rights reserved.
                      </documentation>
                    </annotation -->
                    <element name="purchaseOrder" type="ipo:PurchaseOrderType"/>
                    <element name="comment" type="string"/>
                    <complexType name="PurchaseOrderType">
                      <sequence>
                        <element name="shipTo"     type="ipo:Address"/>
                        <element name="billTo"     type="ipo:Address"/>
                        <element ref="ipo:comment" minOccurs="0"/>
                        <element name="items"      type="ipo:Items"/>
                      </sequence>
                      <attribute name="orderDate" type="date"/>
                    </complexType>
                    <complexType name="Items">
                      <sequence>
                        <element name="item" minOccurs="0" maxOccurs="unbounded">
                          <complexType>
                            <sequence>
                              <element name="productName" type="string"/>
                              <element name="quantity">
                                <simpleType>
                                  <restriction base="positiveInteger">
                                    <maxExclusive value="100"/>
                                  </restriction>
                                </simpleType>
                              </element>
                              <element name="USPrice"    type="decimal"/>
                              <element ref="ipo:comment" minOccurs="0"/>
                              <element name="shipDate"   type="date" minOccurs="0"/>
                            </sequence>
                            <attribute name="partNum" type="ipo:SKU" use="required"/>
                          </complexType>
                        </element>
                      </sequence>
                    </complexType>
                    <complexType name="Address">
                      <sequence>
                        <element name="name"    type="string"/>
                        <element name="street"  type="string"/>
                        <element name="city"    type="string"/>
                        <element name="state"   type="string"/>
                        <element name="country" type="string"/>
                        <element name="zip"     type="string"/>
                      </sequence>
                    </complexType>
                    <simpleType name="SKU">
                      <restriction base="string">
                        <pattern value="[0-9]{3}-[A-Z]{2}"/>
                      </restriction>
                    </simpleType>
                  </schema>',
    LOCAL     => TRUE,
    GENTYPES  => TRUE);
END;
/

-- Create table to hold XML instance documents
DROP TABLE po_tab;

CREATE TABLE po_tab (id NUMBER, xmlcol XMLType) 
 XMLType COLUMN xmlcol
 XMLSCHEMA "http://www.example.com/schemas/ipo.xsd"
 ELEMENT "purchaseOrder";

INSERT INTO po_tab 
  VALUES(1, XMLType(
              '<?xml version="1.0"?>
               <ipo:purchaseOrder
                 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                 xmlns:ipo="http://www.example.com/IPO"
                 xsi:schemaLocation="http://www.example.com/IPO
                                     http://www.example.com/schemas/ipo.xsd"
                 orderDate="1999-12-01">
                 <shipTo>
                   <name>Helen Zoe</name>
                   <street>121 Broadway</street>
                   <city>Cardiff</city>
                   <state>Wales</state>
                   <country>UK</country>
                   <zip>CF2 1QJ</zip>
                 </shipTo>
                 <billTo>
                   <name>Robert Smith</name>
                   <street>8 Oak Avenue</street>
                   <city>Old Town</city>
                   <state>CA</state>
                   <country>US</country>
                   <zip>95819</zip>
                 </billTo>
                 <items>
                   <item partNum="833-AA">
                     <productName>Lapis necklace</productName>
                     <quantity>1</quantity>
                     <USPrice>99.95</USPrice>
                     <ipo:comment>Want this for the holidays!</ipo:comment>
                     <shipDate>1999-12-05</shipDate>
                   </item>
                 </items>
               </ipo:purchaseOrder>'));

例11-2に、SQL関数XMLtransformおよびDBURITypeを使用してスタイルシートを取得する方法を示します。DBURITypeの詳細は、第20章「URIを介したデータのアクセス」を参照してください。

例11-2 XMLTRANSFORMおよびDBURITYPEを使用したスタイルシートの取得

DROP TABLE stylesheet_tab;

CREATE TABLE stylesheet_tab (id NUMBER, stylesheet XMLType);

INSERT INTO stylesheet_tab 
  VALUES (1, 
          XMLType(
            '<?xml version="1.0" ?>
             <xsl:stylesheet version="1.0" 
                             xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
               <xsl:template match="*">
                 <td>
                   <xsl:choose>
                     <xsl:when test="count(child::*) > 1">
                       <xsl:call-template name="nested"/>
                     </xsl:when>
                     <xsl:otherwise>
                       <xsl:value-of select="name(.)"/>:<xsl:value-of 
                                                          select="text()"/>
                     </xsl:otherwise>
                   </xsl:choose>
                 </td>
               </xsl:template>
               <xsl:template match="*" name="nested" priority="-1" mode="nested2">
                 <b>
                   <!-- xsl:value-of select="count(child::*)"/ -->
                   <xsl:choose>
                     <xsl:when test="count(child::*) > 1">
                       <xsl:value-of select="name(.)"/>:<xsl:apply-templates 
                                                          mode="nested2"/>
                     </xsl:when>
                     <xsl:otherwise>
                       <xsl:value-of select="name(.)"/>:<xsl:value-of 
                                                          select="text()"/>
                     </xsl:otherwise>
                   </xsl:choose>
                 </b>
               </xsl:template>
             </xsl:stylesheet>'));

SELECT XMLSerialize(DOCUMENT XMLtransform(x.xmlcol, y.stylesheet)
                    AS varchar2(1000))
  AS result FROM po_tab x, stylesheet_tab y WHERE y.id = 1;

これにより、次の出力が生成されます(ここでは、読みやすくするためにフォーマット出力で示しています)。

RESULT
---------------------------------------------------------
<td>
  <b>ipo:purchaseOrder:
    <b>shipTo:
      <b>name:Helen Zoe</b>
      <b>street:100 Broadway</b>
      <b>city:Cardiff</b>
      <b>state:Wales</b>
      <b>country:UK</b>
      <b>zip:CF2 1QJ</b>
    </b>
    <b>billTo:
      <b>name:Robert Smith</b>
      <b>street:8 Oak Avenue</b>
      <b>city:Old Town</b>
      <b>state:CA</b>
      <b>country:US</b>
      <b>zip:95819</b>
    </b>
    <b>items:</b>
  </b>
</td>

例11-3に、格納されているスタイルシートを使用して、XMLTypeインスタンスを変換する例を示します。例11-3では、例11-2と異なり、格納されているスタイルシートをスカラー副問合せを使用して取得します。

例11-3 XMLTRANSFORMおよび副問合せを使用したスタイルシートの取得

SELECT XMLSerialize(DOCUMENT
                    XMLtransform(
                      x.xmlcol,
                      (SELECT stylesheet FROM stylesheet_tab WHERE id = 1))
                    AS VARCHAR2(1000))
  AS result FROM po_tab x;

例11-4では、一時スタイルシートを使用したXMLTypeインスタンスの変換においてXMLTypeメソッドtransform()を使用します。

例11-4 一時スタイルシートでのメソッドTRANSFORM()の使用

SELECT XMLSerialize(
         DOCUMENT
         x.xmlcol.transform(
           XMLType('<?xml version="1.0" ?>
                  <xsl:stylesheet
                      version="1.0"
                      xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
                    <xsl:template match="*">
                      <td>
                        <xsl:choose>
                          <xsl:when test="count(child::*) > 1">
                            <xsl:call-template name="nested"/>
                          </xsl:when>
                          <xsl:otherwise>
                            <xsl:value-of
                               select =
                                 "name(.)"/>:<xsl:value-of select="text()"/>
                          </xsl:otherwise>
                        </xsl:choose>
                      </td>
                    </xsl:template>
                    <xsl:template match="*" name="nested" priority="-1"
                                  mode="nested2">
                      <b>
                        <!-- xsl:value-of select="count(child::*)"/ -->
                        <xsl:choose>
                          <xsl:when test="count(child::*) > 1">
                            <xsl:value-of select="name(.)"/>:
                            <xsl:apply-templates mode="nested2"/>
                          </xsl:when>
                          <xsl:otherwise>
                            <xsl:value-of
                               select =
                                 "name(.)"/>:<xsl:value-of select="text()"/>
                          </xsl:otherwise>
                        </xsl:choose>
                      </b>
                    </xsl:template>
                  </xsl:stylesheet>'))
         AS varchar2(1000))
  FROM po_tab x;

XMLTypeインスタンスの検証

多くの場合、特定のXML文書が整形式であることに加えて、その文書が特定のXML Schemaに準拠するかどうか(特定のXML Schemaに対して妥当であるかどうか)を認識する必要があります。

バイナリXMLとして格納されたXML Schemaに基づくデータは、挿入または更新時に必ず自動的に完全に検証されます。この検証にはDOMの構築は必要ありません。これはストリーミングを使用して実行され、メモリーの使用を効率的にかつ最小限にします。

オブジェクト・リレーショナル形式で格納されるXMLTypeデータの場合は、完全な検証にDOMの構築が必要なため、メモリー管理の面でコストがかかります。このため、Oracle XML DBは、オブジェクト・リレーショナル形式で格納されるデータが挿入または更新されるときに、完全な検証を自動的には実行しません。

ただし、オブジェクト・リレーショナル形式で格納するためにXMLデータを分解する過程で、Oracle XML DBはXML文書の構造がXML Schemaから導出されたSQLデータ型の定義に準拠しているか確認するため、部分的な検証を実行します。

オブジェクト・リレーショナル形式で格納されたXMLTypeデータに完全な検証が必要であれば、クライアントで検証してからデータベースに挿入したり、更新することを考慮してください。

XML文書で記録された有効性状態を完全に検証または操作するために、次のものを使用できます。

  • Oracle SQL関数XMLIsValidおよびXMLTypeメソッドIsSchemaValid() - 検証プロセスを無条件に実行します。検証状態は記録されません。次の値を戻します。

    • 文書が有効と判断される場合は1

    • 文書が無効と判断される場合または文書の妥当性が判断できない場合は、0

  • XMLTypeメソッドSchemaValidate(): 検証のステータスが0(デフォルト)の場合、検証プロセスを実行します。文書が有効だと判断されると、検証ステータスは1に設定されます(それ以外の場合、ステータスは0のままです)。

  • XMLTypeメソッドisSchemaValidated(): XMLTypeインスタンスの記録済の検証状態を戻します。

  • XMLTypeメソッドsetSchemaValidated(): XMLTypeインスタンスの検証状態を設定(記録)します。

検証状態では、次のように妥当性がわかります。

  • 1は、文書が有効と判断されることを示します。

  • 0は、文書の妥当性が不明であることを示します。検証チェックで文書が無効であるように判断される可能性がありますが、文書が無効であると記録されるわけではありません。検証状態が0と記録された場合にわかるのは、文書の妥当性が不明であることのみです。


関連項目:

  • 「XML Schemaの部分検証と全体検証の比較」

  • Oracle SQL関数XMLIsValidの詳細は、『Oracle Database SQL言語リファレンス』を参照してください。

  • XMLTypeメソッドIsSchemaValid()IsSchemaValidated()SchemaValidate()およびsetSchemaValidated()の詳細は『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。


XMLTypeとして格納されたXMLデータの検証例

この項の各例に、Oracle SQL関数XMLIsValidと、XMLTypeメソッドisSchemaValid()およびschemaValidate()を使用して、Oracle XML DBにXMLTypeとして格納されているXMLデータを検証する方法を示します。

例11-5および例11-6に、PL/SQLメソッドisSchemaValid()を使用して、XML Schemaに対してXMLインスタンスを検証する方法を示します。

例11-5 SQLでメソッドISSCHEMAVALID()を使用したXMLの検証

SELECT x.xmlcol.isSchemaValid('http://www.example.com/schemas/ipo.xsd',
                              'purchaseOrder')
    FROM po_tab x;

例11-6 PL/SQLでメソッドISSCHEMAVALID()を使用したXMLの検証

DECLARE
  xml_instance XMLType;
BEGIN
  SELECT x.xmlcol INTO xml_instance FROM po_tab x WHERE id = 1;
  IF xml_instance.isSchemaValid('http://www.example.com/schemas/ipo.xsd') = 0
    THEN raise_application_error(-20500, 'Invalid Instance');
    ELSE DBMS_OUTPUT.put_line('Instance is valid');
  END IF;
END;
/
Instance is valid
 
PL/SQL procedure successfully completed.

XMLTypeメソッドschemaValidate()INSERTおよびUPDATEトリガー内で使用すると、表に格納されているすべてのインスタンスがXML Schemaに対して検証されたことを確認できます。例11-7に、これを示します。

例11-7 トリガー内でメソッドSCHEMAVALIDATE()を使用したXMLの検証

DROP TABLE po_tab;
CREATE TABLE po_tab OF XMLType 
  XMLSCHEMA "http://www.example.com/schemas/ipo.xsd" ELEMENT "purchaseOrder";

CREATE TRIGGER emp_trig BEFORE INSERT OR UPDATE ON po_tab FOR EACH ROW

DECLARE 
  newxml XMLType;
BEGIn
  newxml := :new.OBJECT_VALUE;
  XMLTYPE.schemavalidate(newxml);
END;
/

例11-8では、Oracle SQL関数XMLIsValidを使用して、次の操作を実行します。

  • XMLTypeインスタンスが指定されたXML Schemaに準拠していることの確認

  • CHECK制約を使用した、受信したXML文書が妥当であることの確認

例11-8 CHECK制約内でXMLISVALIDを使用したXMLの妥当性のチェック

DROP TABLE po_tab;
CREATE TABLE po_tab OF XMLType 
   (CHECK(XMLIsValid(OBJECT_VALUE) = 1))
   XMLSCHEMA "http://www.example.com/schemas/ipo.xsd" ELEMENT "purchaseOrder";

注意:

「XMLTypeインスタンスの検証」の項で示した検証の関数およびプロシージャを使用すると、簡単に妥当性チェックを実行できます。これらのうち、schemaValidateのみが、エラーの発生時に検証が失敗した理由を示します。