7 XMLTypeデータの変換および検証
XSLTスタイルシートを使用してXMLType
データを変換したり、XML Schemaに対してXMLType
インスタンスを検証したりするためのOracle SQL関数およびXMLType
APIがいくつかあります。
- XSL変換とOracle XML DB
組込みのOracle XML DB XSLTプロセッサを使用して、XML Schemaに基づく文書にXSL変換を適用できます。データベース内のXML固有の最適化により、必要なメモリー量が大幅に削減され、解析に関連するオーバーヘッドも削減されてネットワーク・トラフィックが緩和されます。 - XMLTypeインスタンスの検証
多くの場合、特定のXML文書が整形式であることに加えて、その文書が特定のXML Schemaに準拠するかどうか(特定のXML Schemaに対して妥当であるかどうか)を認識する必要があります。
親トピック: Oracle XML DBでのXMLデータの操作
7.1 XSL変換とOracle XML DB
組込みのOracle XML DB XSLTプロセッサを使用して、XML Schemaに基づく文書にXSL変換を適用できます。データベース内のXML固有の最適化により、必要なメモリー量が大幅に削減され、解析に関連するオーバーヘッドも削減されてネットワーク・トラフィックが緩和されます。
W3CのXSLT勧告は、XML文書の形式を別の形式に変換する方法を指定するためのXML言語を定義します。XSLT標準の詳細は、XSL Transformations (XSLT) Version 1.0を参照してください。
変換には、1つのXML Schemaから別のXML Schemaへのマッピング、またはXMLからHTMLやWMLなどの他の形式へのマッピングが含まれる場合があります。
XSL変換は、必要なメモリー量および処理量の面からコストがかかる場合があります。通常のXSLプロセッサでは、処理を開始する前に、ソース・ドキュメント全体とスタイルシートを解析してメモリーにロードする必要があります。通常、XSLプロセッサはDOMを使用して文書やスタイルシートの動的なメモリー表現を行い、任意の部分へのランダム・アクセスを可能にします。次に、XSLプロセッサは、スタイルシートをソース・ドキュメントに適用して、3番目の文書を生成します。
変換の前に文書とスタイルシートを解析してメモリーにロードするには、大量のメモリーとプロセッサ・リソースが必要です。文書のごく一部のみを変換する必要がある場合は、特に非効率です。
Oracle XML DBには、XSL変換をデータベース内で実行するXSLTプロセッサが含まれています。この方法で、XML固有の最適化を実現できます。これによって、変換の実行に必要なメモリー量が大幅に削減され、解析に関連するオーバーヘッドも削減されてネットワーク・トラフィックが緩和されます。
ただし、これらの最適化は、変換対象のソースがスキーマに基づくXML文書である場合にのみ使用できます。その場合、処理を開始する前に解析する必要はありません。Oracle XML DBで遅延ロードされた仮想DOMが、ノードへのアクセス時にオン・デマンドでコンテンツのみをロードします。処理の必要な部分の文書のみがロードされるため、必要なメモリー量が削減されます。
XMLデータは次の方法で変換できます。
-
Oracle Databaseを使用 - Oracle SQL関数の
XMLtransform
、XMLType
のメソッドtransform()
、またはPL/SQLパッケージのDBMS_XSLPROCESSOR
を使用する。 -
中間層を使用 - XSLT Processor for Javaなど、Oracle XML Developer's Kitの変換オプションを使用する。
関連項目:
-
SQL関数
XMLTransform
の詳細は、Oracle Database SQL言語リファレンスを参照してください。 -
PL/SQLパッケージ
DBMS_XSLPROCESSOR
の詳細は、PL/SQL XSLT Processor for XMLType (DBMS_XSLPROCESSOR)およびOracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照してください。 -
XSLT Processor for Javaの詳細は、Oracle XML Developer's Kitプログラマーズ・ガイドを参照してください。
これらの各XML変換方法では、ソースXML文書およびXSLスタイルシートを、XMLType
インスタンスの形式で入力として受け取ります。SQL関数XMLtransform
およびXMLType
メソッドtransform()
では、変換の結果としてXML文書または非XML文書(HTMLなど)が発生します。しかし、PL/SQLパッケージDBMS_XSLPROCESSOR
では、変換の結果は有効なXML文書であることが求められます。パッケージDBMS_XSLPROCESSOR
を使用した変換によって生成されるHTMLデータは、XHTMLデータ(つまり、有効なXMLデータと有効なHTMLデータ)である必要があります。
例7-1は、XSLTスタイルシートPurchaseOrder.xsl
の一部を示しています。完全なスタイルシートは、XSLTスタイルシートの例、PurchaseOrder.xslを参照してください。
例7-1のスタイルシートに関して、Oracle XML DB固有のものはありません。スタイルシートは、XMLType
表または列に格納でき、Oracle XML DBリポジトリ内にXML Schemaに基づかないXMLデータとしても格納できます。
例7-1 XSLTスタイルシートの例: PurchaseOrder.xsl
<?xml version="1.0" encoding="WINDOWS-1252"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xdb="http://xmlns.oracle.com/xdb" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <xsl:template match="/"> <html> <head/> <body bgcolor="#003333" text="#FFFFCC" link="#FFCC00" vlink="#66CC99" alink="#669999"> <FONT FACE="Arial, Helvetica, sans-serif"> <xsl:for-each select="PurchaseOrder"/> <xsl:for-each select="PurchaseOrder"> <center> <span style="font-family:Arial; font-weight:bold"> <FONT COLOR="#FF0000"> <B>PurchaseOrder </B> </FONT> </span> </center> <br/> <center> <xsl:for-each select="Reference"> <span style="font-family:Arial; font-weight:bold"> <xsl:apply-templates/> </span> </xsl:for-each> </center> </xsl:for-each> <P> <xsl:for-each select="PurchaseOrder"> <br/> </xsl:for-each> <P/> <P> <xsl:for-each select="PurchaseOrder"> <br/> </xsl:for-each> </P> </P> <xsl:for-each select="PurchaseOrder"/> <xsl:for-each select="PurchaseOrder"> <table border="0" width="100%" BGCOLOR="#000000"> <tbody> <tr> <td WIDTH="296"> <P> <B> <FONT SIZE="+1" COLOR="#FF0000" FACE="Arial, Helvetica, sans-serif">Internal</FONT> </B> </P> ... </td> <td width="93"/> <td valign="top" WIDTH="340"> <B> <FONT COLOR="#FF0000"> <FONT SIZE="+1">Ship To</FONT> </FONT> </B> <xsl:for-each select="ShippingInstructions"> <xsl:if test="position()=1"/> </xsl:for-each> <xsl:for-each select="ShippingInstructions"> </xsl:for-each> ...
- SQL関数XMLTRANSFORMおよびXMLTypeメソッドTRANSFORM()
SQL関数XMLtransform
では、XSLTスタイルシートを使用してXML文書を変換します。スタイルシートで指定したように、処理された出力をXML、HTMLなどで戻します。 - DBUriサーブレットを使用したXSL変換
DBUriサーブレットで生成されたXMLコンテンツに、XSL変換を適用できます。
親トピック: XMLTypeデータの変換および検証
7.1.1 SQL関数XMLTRANSFORMおよびXMLTypeメソッドTRANSFORM()
SQL関数XMLtransform
では、XSLTスタイルシートを使用してXML文書を変換します。スタイルシートで指定したように、処理された出力をXML、HTMLなどで戻します。
図7-1に、Oracle SQL関数XMLtransform
の構文を示します。この関数は引数としてXMLType
インスタンスとXSLTスタイルシートを受け取ります。スタイルシートはXMLType
インスタンスまたはVARCHAR2
文字列リテラルのいずれかです。スタイルシートをインスタンスに適用し、XMLType
インスタンスを戻します。
Oracle SQL関数XMLtransform
のかわりにXMLType
メソッドtransform()
を使用することもできます。どちらも機能は同じです。
図7-2に、XSLTスタイルシートを使用してXMLtransform
がXML文書を変換する方法を示します。XSLTスタイルシートで指定したように、処理された出力をXML、HTMLなどで戻します。データベース内にXMLType
として格納されたXML文書の取得または生成時は、通常はXMLtransform
を使用します。
関連項目:
- XMLTRANSFORMおよびXMLType.transform()の例
Oracle SQL関数XMLtransform
およびXMLType
メソッドtransform()
を使用して、XMLType
として格納されているXMLデータを様々な形式に変換する方法について例で説明します。
親トピック: XSL変換とOracle XML DB
7.1.1.1 XMLTRANSFORMおよびXMLType.transform()の例
Oracle SQL関数XMLtransform
およびXMLType
メソッドtransform()
を使用して、XMLType
として格納されているXMLデータを様々な形式に変換する方法について例で説明します。
例7-2では、この章の他の例を実行するために必要なXML Schemaおよび表を設定します。ここに示したdeleteSchema
のコールは、XML Schemaの作成前に既存のスキーマがないようにするためのものです。そのようなスキーマが存在しない場合は、deleteSchema
でエラーが発生します。
例7-3ではXSLTスタイルシートを格納してからそれを取得し、Oracle SQL関数のXMLTransform
でそれを使用して、例7-2で格納したXMLデータを変換します。
例7-4では、その場で作成したXSLスタイルシートでXMLType
のメソッドtransform()
を使用します。
例7-5では、XMLTransform
を使用してXSLスタイルシートを適用し、HTMLコードを生成します。PL/SQLコンストラクタXDBURIType
は、Oracle XML DBリポジトリからXSLスタイルシートを読み取ります。
例7-5に、HTML結果の一部のみを示します。省略した部分は、省略記号(. . .
)で示しています。図7-3に、変換された結果がWebブラウザでどのように表示されるかを示します。
例7-2 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 purchase-order documents, and insert the 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>'));
例7-3 SQL関数XMLTRANSFORMを使用してXSLスタイルシートを適用
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>
例7-4 一時XSLスタイルシートでのXMLTypeメソッド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;
例7-5 XMLTRANSFORMを使用して、XDBURITypeで取得したXSLスタイルシートを適用
SELECT XMLTransform( OBJECT_VALUE, XDBURIType('/source/schemas/poSource/xsl/purchaseOrder.xsl').getXML()) FROM purchaseorder WHERE XMLExists('$p/PurchaseOrder[Reference="SBELL-2002100912333601PDT"]' PASSING OBJECT_VALUE AS "p"); XMLTRANSFORM(OBJECT_VALUE, XDBURITYPE('/SOURCE/SCHEMAS/POSOURCE/XSL/PURCHASEORDER.XSL').GET --------------------------------------------------------------------------------------------- <html xmlns:xdb="http://xmlns.oracle.com/xdb" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <head/> <body bgcolor="#003333" text="#FFFFCC" link="#FFCC00" vlink="#66CC99" alink="#669999"> <FONT FACE="Arial, Helvetica, sans-serif"> <center> <span style="font-family:Arial; font-weight:bold"> <FONT COLOR="#FF0000"> <B>PurchaseOrder </B> </FONT> </span> </center> <br/> <center> <span style="font-family:Arial; font-weight:bold">SBELL-2002100912333601PDT</span> </center> <P> <br/> <P/> <P> <br/> </P> </P> <table border="0" width="100%" BGCOLOR="#000000"> <tbody> <tr> <td WIDTH="296"> <P> <B> <FONT SIZE="+1" COLOR="#FF0000" FACE="Arial, Helvetica, sans-serif">Internal</FONT> </B> </P> <table border="0" width="98%" BGCOLOR="#000099">
. . .
</table> </td> <td width="93"> </td> <td valign="top" WIDTH="340"> <B> <FONT COLOR="#FF0000"> <FONT SIZE="+1">Ship To</FONT> </FONT> </B> <table border="0" BGCOLOR="#999900"> . . . </table> </td> </tr> </tbody> </table> <br/> <B> <FONT COLOR="#FF0000" SIZE="+1">Items:</FONT> </B> <br/> <br/> <table border="0"> . . . </table> </FONT> </body> </html> 1 row selected.
7.1.2 DBUriサーブレットを使用したXSL変換
DBUriサーブレットで生成されたXMLコンテンツに、XSL変換を適用できます。
図7-3に、このような変換の結果を示します。URLは次のとおりです(ここでは、分割して切り捨てられています)。
http://localhost:8080/oradb/SCOTT/PURCHASEORDER/ROW/PurchaseOrder[Reference="SBELL-2003030912333601PDT"]
contenttype=text/html&transform=/home/SCOTT/xsl/purchaseOrder.xsl...
パラメータtransform
が存在するため、DBUriサーブレットはSQL関数XMLTransform
を使用して、/home/SCOTT/xsl/purchaseOrder.xsl
にあるXSLスタイルシートを、メインのURLで識別されるPurchaseOrder
文書に適用します。変換の結果、HTMLコードがブラウザに返されて表示されます。また、URLでは、パラメータcontentType
を使用して、最後の文書のMIMEタイプがtext/html
になることを指定します。
図7-4に、HTML文書として表示されたdepartments
表を示します。これを実行するためにコードは必要ありません。必要なのは、SQL/XML関数に基づくXMLType
ビュー、業界標準のXSLスタイルシート、およびDBUri
サーブレットのみです。
親トピック: XSL変換とOracle XML DB
7.2 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の部分検証と全体検証
XML Schemaに基づく文書をデータベースに挿入するとき、これらを部分的または完全に検証できます。 - XMLTypeとして格納されたXMLデータの検証例
ここでの例では、Oracle SQL関数XMLIsValid
と、XMLType
メソッドisSchemaValid()
およびschemaValidate()
を使用して、Oracle XML DBにXMLType
として格納されているXMLデータを検証する方法を示します。
関連項目:
-
SQL関数
XMLIsValid
の詳細は、Oracle Database SQL言語リファレンスを参照してください。 -
XMLType
メソッドIsSchemaValid()
、IsSchemaValidated()
、SchemaValidate()
およびsetSchemaValidated()
の詳細はOracle Database PL/SQLパッケージおよびタイプ・リファレンスを参照してください。
親トピック: XMLTypeデータの変換および検証
7.2.1 XML Schemaの部分検証と全体検証
XML Schemaに基づく文書をデータベースに挿入するとき、これらを部分的または完全に検証できます。
- 部分検証
バイナリXML記憶域の場合、XML Schemaに基づく文書がXMLType
表または列に挿入されるたびに、Oracle XML DBによりこれらの文書の全体検証が実行されます。オブジェクト・リレーショナルXML記憶域の場合は、部分検証のみが実行されます。これは、オブジェクト・リレーショナル記憶域の場合、XML Schemaの完全な検証はパフォーマンスの面で非常にコストが高くなるためです。 - 全体検証
XML Schemaに基づくデータをバイナリXML記憶域にロードすると、ターゲットXML Schemaに対してデータの全体検証が行われます。オブジェクト・リレーショナルXMLType
記憶域の場合、いつでも全体検証を強制できます。
親トピック: XMLTypeインスタンスの検証
7.2.1.1 部分検証
バイナリXML記憶域の場合、XML Schemaに基づく文書がXMLType
表または列に挿入されるたびに、Oracle XML DBによりこれらの文書の全体検証が実行されます。オブジェクト・リレーショナルXML記憶域の場合は、部分検証のみが実行されます。これは、オブジェクト・リレーショナル記憶域の場合、XML Schemaの完全な検証はパフォーマンスの面で非常にコストが高くなるためです。
部分検証では、文書内に必須の要素および属性がすべて存在すること、および予期しない要素または属性のないことが確認されるのみです。つまり、XML文書の構造がXML Schemaから導出されたSQLデータ型定義に準拠していることのみが確認されます。部分検証では、インスタンス・ドキュメントがXML Schemaに完全に準拠しているかどうかは確認されません。
例7-6に、オブジェクト・リレーショナル形式で格納されている表PurchaseOrder
にXML文書を挿入する間に部分検証が失敗した例を示します。
例7-6 不適切なXML文書の挿入時に発生するエラー(部分検証)
INSERT INTO purchaseorder
VALUES(XMLType(bfilename('XMLDIR', 'InvalidElement.xml'),
nls_charset_id('AL32UTF8')));
VALUES(XMLType(bfilename('XMLDIR', 'InvalidElement.xml'),
*
ERROR at line 2:
ORA-30937: No schema definition for 'UserName' (namespace '##local') in parent
'/PurchaseOrder'
親トピック: XML Schemaの部分検証と全体検証
7.2.1.2 全体検証
XML Schemaに基づくデータをバイナリXML記憶域にロードすると、ターゲットXML Schemaに対してデータの全体検証が行われます。オブジェクト・リレーショナルXMLType
記憶域の場合、いつでも全体検証を強制できます。
全体検証を強制するには、次のいずれかを使用します。
-
表レベルの
CHECK
制約 -
PL/SQLの
BEFORE INSERT
トリガー
どちらの方法でも、妥当なXML文書のみがXMLType
表に格納されることが保証されます。
TABLE CHECK
制約を使用する方法のメリットは、コーディングが簡単なことです。この方法のデメリットは、この方法がOracle SQL関数XMLisValid
に基づいているため、XML文書が妥当であるかどうかしか示されないことです。XML文書が妥当でない場合、TABLE CHECK
制約では、その理由についての情報を提供できません。
BEFORE INSERT
トリガーの場合は、必要なコーディングが表レベルの制約よりわずかに多くなります。このトリガーでは、XMLType
のschemaValidate()
メソッドを起動してXML文書を検証します。schemaValidate()
を使用するメリットは、例外が発生した場合にそのインスタンス・ドキュメントの問題点に関する追加情報が提供されることです。また、BEFORE INSERT
トリガーを使用すると、無効な文書が存在する場合に適切な処置を行うことができます。
- XML Schemaの全体検証による処理時間とメモリーの消費
バイナリXML記憶域を使用していない場合は、XML Schemaの全体検証を実行すると、多くの処理時間とメモリーが消費されます。このため、XML Schemaの全体検証は、必要なときにのみ実行してください。
親トピック: XML Schemaの部分検証と全体検証
7.2.1.2.1 XML Schemaの全体検証による処理時間とメモリーの消費
バイナリXML記憶域を使用していない場合は、XML Schemaの全体検証を実行すると、多くの処理時間とメモリーが消費されます。このため、XML Schemaの全体検証は、必要なときにのみ実行してください。
XML文書を検証するアプリケーションを使用する場合は、全体検証に関連するオーバーヘッドを回避することによって、バイナリ以外のXML記憶域での全体のスループットを向上させることができます。受信するXML文書の妥当性について確認できない場合は、スキーマに対して妥当なXML文書のみがXMLType
表または列に含まれていることをデータベースで確認できます。
例7-7に、CHECK
制約をXMLType
表に追加してXML Schemaの全体検証を実行する方法を示します。例7-7のXML文書InvalidReference
は、XML Schemaに従った妥当なXML文書ではありません。XML Schemaでは、Reference
要素に関連付けられたテキスト・ノードの最小長を18文字とすることが定義されています。この例に示す文書では、ノードの値はSBELL-20021009
で、14文字の長さしかありません。部分検証ではこのエラーは捕捉されません。制約またはトリガーがないかぎり、この文書をデータベースに挿入することが可能です。
例7-7 CHECK制約を使用したXML Schemaの全体検証の実施
ALTER TABLE purchaseorder
ADD CONSTRAINT validate_purchaseorder
CHECK (XMLIsValid(OBJECT_VALUE) = 1);
Table altered.
INSERT INTO purchaseorder
VALUES (XMLType(bfilename('XMLDIR', 'InvalidReference.xml'),
nls_charset_id('AL32UTF8')));
INSERT INTO purchaseorder
*
ERROR at line 1:
ORA-02290: check constraint (QUINE.VALIDATE_PURCHASEORDER) violated
疑似列OBJECT_VALUE
を使用すると、トリガー内からXMLType
表のコンテンツにアクセスできます。例7-8は、BEFORE INSERT
トリガーを使用して、XMLType
表に挿入されるデータが、指定されたXML Schemaに準拠していることを検証する方法を示しています。
例7-8 BEFORE INSERTトリガーを使用したXML Schemaの全体検証の実施
CREATE OR REPLACE TRIGGER validate_purchaseorder
BEFORE INSERT ON purchaseorder
FOR EACH ROW
BEGIN
IF (:new.OBJECT_VALUE IS NOT NULL) THEN :new.OBJECT_VALUE.schemavalidate();
END IF;
END;
/
INSERT INTO purchaseorder
VALUES (XMLType(bfilename('XMLDIR', 'InvalidReference.xml'),
nls_charset_id('AL32UTF8')));
VALUES (XMLType( bfilename('XMLDIR', 'InvalidReference.xml'),
*
ERROR at line 2:
ORA-31154: invalid XML document
ORA-19202: Error occurred in XML processing
LSX-00221: "SBELL-20021009" is too short (minimum length is 18)
LSX-00213: only 0 occurrences of particle "sequence", minimum is 1
ORA-06512: at "SYS.XMLTYPE", line 354
ORA-06512: at "QUINE.VALIDATE_PURCHASEORDER", line 3
ORA-04088: error during execution of trigger 'QUINE.VALIDATE_PURCHASEORDER'
親トピック: 全体検証
7.2.2 XMLTypeとして格納されたXMLデータの検証例
ここでの例は、Oracle SQL関数XMLIsValid
と、XMLType
メソッドisSchemaValid()
およびschemaValidate()
を使用して、Oracle XML DBにXMLType
として格納されているXMLデータを検証する方法を示しています。
例7-9および例7-10に、PL/SQLメソッドisSchemaValid()
を使用して、XML Schemaに対してXMLインスタンスを検証する方法を示します。
XMLType
メソッドschemaValidate()
をINSERT
およびUPDATE
トリガー内で使用すると、表に格納されているすべてのインスタンスがXML Schemaに対して検証されたことを確認できます。例7-11に、これを示します。
例7-12では、Oracle SQL関数XMLIsValid
を使用して、次の操作を実行します。
-
XMLType
インスタンスが指定されたXML Schemaに準拠していることの確認 -
CHECK
制約を使用した、受信したXML文書が妥当であることの確認
注意:
XMLTypeインスタンスの検証で示した検証の関数およびプロシージャを使用すると、簡単に検証チェックを実行できます。これらのうち、schemaValidate
のみが、エラーの発生時に検証が失敗した理由を示します。
例7-9 SQLでメソッドISSCHEMAVALID()を使用したXMLの検証
SELECT x.xmlcol.isSchemaValid('http://www.example.com/schemas/ipo.xsd',
'purchaseOrder')
FROM po_tab x;
例7-10 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.
例7-11 トリガー内でメソッド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;
/
例7-12 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インスタンスの検証