8 Cを使用したXML差分の検出
2つのExtensible Markup Language (XML)入力間の差分を求め、差分を一方のXML文書に適用する方法について説明します。
8.1 CにおけるXMLDiffの概要
Oracle XmlDiff
を使用して、類似した2つのXML文書の差分を定義できます。これにより、差分を示すXdiff
インスタンス・ドキュメントが生成されます。Xdiff
インスタンス・ドキュメントは、XMLスキーマの1つであるXdiff
スキーマに準拠するXML文書です。
XmlPatch
を使用して、Xdiff
インスタンス・ドキュメントを受け取り、他の文書に変更を適用できます。このプロセスを使用して、同一の変更を多くのXML文書に適用できます。
XmlDiff
では、入力と出力にDocument Object Model (DOM)アプリケーション・プログラミング・インタフェース(API)のみがサポートされます。
XmlPatch
もまた、DOMの入力およびパッチ文書をサポートしています。
XmlDiff
およびXmlPatch
は、C APIまたはコマンドライン・ツールを介して使用できます。2つのStructured Query Language (SQL)関数によって公開されます。
XmlHash
C APIは、XMLツリーまたはサブツリーのハッシュ値を計算するために提供されます。2つのツリーまたはサブツリー間のハッシュ値が同数の場合、これらのツリーは非常に高い確率で同一です。
8.2 XMLDiffの使用
XmlDiff
は、2つの入力文書を示すツリーを比較して差分を検出します。この2つの入力文書では、同一のキャラクタ・セット・エンコーディングを使用する必要があります。Xdiff
(出力)インスタンス・ドキュメントには、入力文書のデータ・エンコーディング(DOMエンコーディング)と同一のエンコーディングが含まれます。
8.2.1 比較の最適化に関するユーザー・オプション
比較に関する最適化オプションとして、グローバル最適化とローカル最適化の2つがあります。
-
グローバル最適化(デフォルト)
文書ツリー全体が比較されます。
-
ローカル最適化
兄弟関係のレベルで比較が行われます。ローカル最適化では、2つのツリーの対応する親の下にある兄弟関係が比較されます。
グローバル最適化では、大きな文書に対してより多くの時間および領域を使用できますが、生成されるのは常に最小の差分セット(最適差分)です。ローカル最適化の方が処理速度は速いですが、最適差分は生成されない場合があります。
8.2.2 ハッシュに関するユーザー・オプション
一般的に、ハッシュによりグローバル最適化が早くなりますが、質が若干落ちる可能性もあります。ローカル最適化では、ハッシュにより差分出力の質が改善されます。異なるハッシュのレベルを使用すると、ローカル差分およびグローバル差分の両方が生成される可能性があります。ローカルおよびグローバルの両方の最適化に関するハッシュの使用を指定できます。
ハッシュを指定するには、hashLevel
パラメータを入力します。hashLevel
が1より大きい場合、DOMHash
値を使用して、差分がdepth >= hashLevel
のすべてのサブツリーを比較できます。ハッシュ値が同一の場合は、サブツリーも同一と推定されます。
8.2.3 XmlDiffでの入力文書の見方
XmlDiff
での入力文書の処理方法について説明します。
XmlDiff
は、比較の実行中、属性順に差分を無視します。
XmlDiff
はDocType
宣言を無視します。ファイルはDocument Type Definition (DTD)に対して検証されません。
名前空間の接頭辞が同一の名前空間Universal Resource Identifier (URI)を参照する場合は、XmlDiff
は名前空間の接頭辞における差分を無視します。それ以外の場合で、2つのノードに同じローカル名および内容が含まれていて名前空間URIが異なる場合は、差分が明示されます。
注意:
XmlDiff
は入力文書上で、スキーマに基づかない方法で動作します。要素または属性上で、型を認識する方法では動作しません。
8.2.4 XmlDiffコマンドライン・ユーティリティの使用
ユーティリティXmlDiff
のコマンドライン・オプションについて説明します。
表8-1 C言語に関するXmlDiffコマンドライン・オプション
オプション | 説明 |
---|---|
|
デフォルトの入力ファイルのエンコーディングを指定します。XMLファイルでエンコーディングが指定されていない場合、このエンコーディングは入力対象とみなされます。 |
|
出力/データのエンコーディングを指定します。DOMおよび |
|
ハッシュのレベルを指定します。
|
|
グローバル最適化(デフォルト)を設定します。 |
|
ローカル最適化を設定します。 |
|
使用方法のヘルプを表示します。 |
|
更新操作を無効にします。 |
8.2.5 入力文書のサンプル
入力XML文書のサンプルを示します。
例8-1は、XmlDiff
およびXmlPatch
の使用による更新を説明するXML文書のサンプルです。いくつかの変更が続きます。
次のアクションが結果的に発生すること以外は、例8-1とほぼ同じ内容の別のファイルbook2.xml
があるとします。
-
「The Eleventh Commandment」を削除(
delete-node
操作の1つ)。 -
「C++ Primer」の国コードを米国から英国に変更(
update-node
操作の1つ)。 -
「Emperor's New Mind」に説明を追加(
append-node
操作の1つ)。 -
「Evening News」に版を追加(
insert-node-before
操作の1つ)。 -
「Evening News」の価格を更新(
update-node
操作の1つ)。
例8-1 book1.xml
<?xml version="1.0"?>
<booklist xmlns="http://booklist.oracle.com">
<book>
<title>Twelve Red Herrings</title>
<author>Jeffrey Archer</author>
<publisher>Harper Collins</publisher>
<price>7.99</price>
</book>
<book>
<title language="English">The Eleventh Commandment</title>
<author>Jeffrey Archer</author>
<publisher>McGraw Hill</publisher>
<price>3.99</price>
</book>
<book>
<title language="English" country="USA">C++ Primer</title>
<author>Lippmann</author>
<publisher>Harper Collins</publisher>
<price>4.99</price>
</book>
<book>
<title>Emperor's New Mind</title>
<author>Roger Penrose</author>
<publisher>Oxford Publishing Company</publisher>
<price>15.9</price>
</book>
<book>
<title>Evening News</title>
<author>Arthur Hailey</author>
<publisher>MacMillan Publishers</publisher>
<price>9.99</price>
</book>
</booklist>
8.2.6 Xdiffインスタンス・ドキュメントのサンプル
Xdiff
インスタンス・ドキュメントのサンプルを示します。
この項では、前の項で説明された2つのXMLファイルの比較により生成されたXdiff
インスタンス・ドキュメントを示します。次の項では、XML処理命令およびこの文書での操作について説明します。
次のようにしてXmlDiff
を起動します。
> xmldiff book1.xml book2.xml
この表では、引数およびフラグに関するサンプル・アプリケーションについても見ることができます。
例8-2 Xdiffインスタンス・ドキュメントのサンプル
<?xml version="1.0" encoding="UTF-8"?>
<xd:xdiff xsi:schemaLocation="http://xmlns.oracle.com/xdb/xdiff.xsd
xmlns:xd="http://xmlns.oracle.com/xdb/xdiff.xsd" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:oraxdfns_0="http://booklist.oracle.com">
<?oracle-xmldiff operations-in-docorder="true" output-model="snapshot"
diff-algorithm="global"?>
<xd:delete-node xd:node-type="element" xd:xpath="/oraxdfns_0
:booklist[1]/oraxdfns_0:book[2]"/>
<xd:update-node xd:node-type="attribute"
xd:parent-xpath="/oraxdfns_0:booklist[1]/oraxdfns_0:book[3]/oraxdfns_0
:title[1]" xd:attr-local="country">
<xd:content>US</xd:content>
</xd:update-node>
<xd:append-node xd:node-type="element" xd:parent-xpath="/oraxdfns_0
:booklist[1]/oraxdfns_0:book[4]">
<xd:content>
<oraxdfns_0:description> This is a classic </oraxdfns_0:description>
</xd:content>
</xd:append-node>
<xd:insert-node-before xd:node-type="element" xd:xpath="/oraxdfns_0
:booklist[1]/oraxdfns_0:book[5]/oraxdfns_0:author[1]">
<xd:content>
<oraxdfns_0:edition>Hardcover</oraxdfns_0:edition>
</xd:content>
</xd:insert-node-before>
<xd:update-node xd:node-type="text" xd:xpath="/oraxdfns_0
:booklist[1]/oraxdfns_0:book[5]/oraxdfns_0:price[1]/text()[1]">
<xd:content>12.99</xd:content>
</xd:update-node>
</xd:xdiff>
8.2.7 出力モデルおよびXML処理命令
Xdiff
インスタンス・ドキュメントは、XML処理命令(前の項の太字表示箇所)を使用して、差分検出処理の特定の側面を表示します。
「Xdiffスキーマ」を参照してください。命令および関連オプションは次のとおりです。
-
operations-in-docorder
: オプションはtrue
またはfalse
です。-
true
:Xdiff
インスタンス・ドキュメントは、文書内と同じ順で最初の文書からノードを参照します。 -
false
:Xdiff
インスタンス・ドキュメントは、文書内と同じ順で最初の文書からノードを参照しません。
グローバル最適化の出力は
operations-in-docorder
要件に適合しますが、ローカル最適化では適合しません。 -
-
output-model
: オプションは次のとおりです。-
snapshot
:Xmldiff
はスナップショット・モデルで出力を生成し、UNIXのdiffモデルに従います。入力文書にどの操作も適用しない場合は、XPath
が使用されます。これはデフォルトです。operations-in-docorder
がtrue
に設定され、XPath
が単純である場合のみ、XmlPatch
はこのモデルの処理を実行できます。単純なXPath
は子の軸をワイルド・カードなしで要求し、述語の位置を/root[1]/child[2]/text()[2]
のように使用する必要があります。 -
current
: 各操作は、前の操作までのすべての操作が入力文書に適用されているようにXPath
を使用します。XmlDiff
が差分を現在のモデルで生成しない場合でも、XmlPatch
は手作業で作成したdiff
文書を現在のモデルで処理できます。
-
-
diff-algorithm
: このオプションはどの最適化が差分を生成するかを示します。-
グローバル最適化
-
ローカル最適化
-
関連項目
8.2.8 Xdiff操作
XmlDiff
は、Xdiff
インスタンス・ドキュメントによって明示される操作を使用して差分を検出します。XmlDiff
操作について説明します。
表8-2 Xdiff操作の属性
属性 | 説明 |
---|---|
|
オペランド・ノードの親ノードの |
|
オペランド・ノードのタイプを指定します。 |
|
追加または挿入される新規のサブツリーまたは値を指定する子要素です。 |
Xdiff
インスタンス・ドキュメントに表示されるXdiff
操作は、次のとおりです。
-
append-node
:append-node
要素により、指定されたタイプのノードが指定された親の最後の子へ追加されるように指定されます。 -
insert-node-before
:insert-node-before
要素により、指定されたタイプのノードが指定された参照ノードの前に挿入されるように指定されます。 -
delete-node
:delete-node
要素により、削除されるノードにそのすべての子が含まれるように指定されます。この要素を使用して、要素やコメントなどを削除できます。 -
update-node
:update-node
は、指定されたXPath
式を含むノードに関連付けられた値が指定された新規の値に更新されるように指定します。内容は、テキスト・ノードに関する値です。属性の値は、属性ノードに関する値です。-
テキスト・ノードの更新
-
update node操作の生成はユーザーによってオフにできます。
-
属性の値は、属性ノードに関する値です。
-
update-node
は、グローバル最適化によってのみテキスト・ノードに対して生成されます。
-
-
要素の更新:
-
XmlDiff
は、要素ノードに対して更新操作を生成しません。Xdiff
インスタンス・ドキュメントを手動で変更して、XmlPatch
を操作する更新操作を作成できます。または、Xdiff
インスタンス・ドキュメントを完全に手書きで入力することも可能です。更新操作に関わる要素のすべての子は削除されます。内容ノードで指定された新規のサブツリーは、すべてインポートされます。
-
-
8.2.9 Xdiffインスタンス・ドキュメントの形式
XmlDiff
の出力であるXdiff
インスタンス・ドキュメントは、Xdiff
XMLスキーマに準拠するXML文書です。出力文書には、2つの入力文書間の差分を示す一連の操作が含まれます。最初の文書に差分を適用する場合は、2番目の文書を取得します。
8.2.10 Xdiffスキーマ
Xdiff
インスタンス・ドキュメント(出力)が従うXdiff
XMLスキーマを示します。
例8-3 Xdiffスキーマ: xdiff.xsd
<schema targetNamespace="http://xmlns.oracle.com/xdb/xdiff.xsd"
xmlns="http://www.w3.org/2001/XMLSchema"
xmlns:xd="http://xmlns.oracle.com/xdb/xdiff.xsd"
version="1.0" elementFormDefault="qualified"
attributeFormDefault="qualified">
<annotation>
<documentation xml:lang="en">
Defines the structure of XML documents that capture the difference
between two XML documents. Changes that are not supported by Oracle
XmlDiff may not be expressible in this schema.
'oracle-xmldiff' PI in Xdiff document:
We use 'oracle-xmldiff' PI to describe certain aspects of the diff.
The PI denotes values for 'operations-in-docorder' and 'output-model'.
The output of XmlDiff has the PI always. If the user hand-codes a diff doc
then it must also have the PI in it as the first child of top level xdiff
element, to be able to call XmlPatch.
operations-in-docorder:
Can be either 'true' or 'false'.
If true, the operations in the diff document refer to the
elements of the input doc in the same order as document order. Output of
global algorithm meets this requirement while local does not.
output-model:
output models for representing the diff. Can be either 'Snapshot' or
'Current'.
Snapshot model:
Each operation uses Xpaths as if no operations
have been applied to the input document. (like UNIX diff)
This is the model used in the output of XmlDiff. XmlPatch works with
this (and the current model too).
For XmlPatch to handle this model, "operations-in-docorder" must be
true and the Xpaths must be simple. (see XmlDif C API documentation).
Current model:
Each operation uses Xpaths as if all operations till the previous one
have been applied to the input document. Works with XmlPatch even if
the 'operations-in-docorder' criterion is not met and the xpaths are
not simple.
<!-- Example:
<?oracle-xmldiff operations-in-docorder="true" output-model=
"snapshot" diff-algorithm="global"?>
-->
</documentation>
</annotation>
<!-- Enumerate the supported node types -->
<simpleType name="xdiff-nodetype">
<restriction base="string">
<enumeration value="element"/>
<enumeration value="attribute"/>
<enumeration value="text"/>
<enumeration value="cdata"/>
<enumeration value="entity-reference"/>
<enumeration value="entity"/>
<enumeration value="processing-instruction"/>
<enumeration value="notation"/>
<enumeration value="comment"/>
</restriction>
</simpleType>
<element name="xdiff">
<complexType>
<choice minOccurs="0" maxOccurs="unbounded">
<element name="append-node">
<complexType>
<sequence>
<element name="content" type="anyType"/>
</sequence>
<attribute name="node-type" type="xd:xdiff-nodetype"/>
<attribute name="xpath" type="string"/>
<attribute name="parent-xpath" type="string"/>
<attribute name="attr-local" type="string"/>
<attribute name="attr-nsuri" type="string"/>
</complexType>
</element>
<element name="insert-node-before">
<complexType>
<sequence>
<element name="content" type="anyType"/>
</sequence>
<attribute name="xpath" type="string"/>
<attribute name="node-type" type="xd:xdiff-nodetype"/>
</complexType>
</element>
<element name="delete-node">
<complexType>
<attribute name="node-type" type="xd:xdiff-nodetype"/>
<attribute name="xpath" type="string"/>
<attribute name="parent-xpath" type="string"/>
<attribute name="attr-local" type="string"/>
<attribute name="attr-nsuri" type="string"/>
</complexType>
</element>
<element name="update-node">
<complexType>
<sequence>
<element name="content" type="anyType"/>
</sequence>
<attribute name="node-type" type="xd:xdiff-nodetype"/>
<attribute name="parent-xpath" type="string"/>
<attribute name="xpath" type="string"/>
<attribute name="attr-local" type="string"/>
<attribute name="attr-nsuri" type="string"/>
</complexType>
</element>
<element name="rename-node">
<complexType>
<sequence>
<element name="content" type="anyType"/>
</sequence>
<attribute name="xpath" type="string"/>
<attribute name="node-type" type="xd:xdiff-nodetype"/>
</complexType>
</element>
</choice>
<attribute name="xdiff-version" type="string"/>
</complexType>
</element>
</schema>
8.2.11 アプリケーションでのXMLDiffの使用
アプリケーションでは、XmlDiff
は、入力文書のソース・タイプおよび場所を引数とします。ソース・タイプは、URL、ファイル、orastream
およびstream
コンテキスト・ポインタ、バッファ、buffer_length
ポインタ、またはDOM文書要素(docelement
)へのポインタです。
XmlDiff
は、Xdiff
インスタンス・ドキュメントに関するDOMの文書ノードを戻します。
比較の実行前にDOMとして2つの文書が提供されていない場合、XmlDiffは2つの文書に対してDOMを構築します。
関連項目:
XmlDiff
の動作を制御するフラグのC APIの詳細は、『Oracle Database XML C APIリファレンス』を参照してください
例8-4 XMLDiffアプリケーション
# include <xmldf.h> ... xmlctx *xctx; xmldocnode *doc1, *doc2, *doc3; uword hash_level; oratext *s, *inp1 = "book1.xml", *inp2="book2.xml"; xmlerr err; ub4 flags; flags = 0; /* defaults : global algorithm */ hash_level = 0; /* no hashing */ /* create XML meta context */ if (!(xctx = XmlCreate(&err, (oratext *) "XmlDiff", NULL))) { printf("Failed to create XML context, error %u\n", (unsigned) err); err_exit("Exiting"); } /* Load the two input files */ if (!(doc1 = XmlLoadDom(xctx, &err, "file", inp1, "discard_whitespace", TRUE, NULL))) { printf("Parsing first file failed, error %u\n", (unsigned)err); err_exit((oratext *)"Exiting."); } if (!(doc2 = XmlLoadDom(xctx, &err, "file", inp2, "discard_whitespace", TRUE, NULL))) { printf("Parsing second file failed, error %u\n", (unsigned)err); err_exit((oratext *)"Exiting."); } /* run XmlDiff on the DOM trees. */ doc3 = XmlDiff(xctx, &err, flags, XMLDF_SRCT_DOM, doc1, NULL, XMLDF_SRCT_DOM, doc2, NULL,hash_level, NULL); if(!doc3) printf("XmlDiff Failed, error %u\n", (unsigned)err); else { if(err != XMLERR_OK) printf("XmlDiff returned error %u\n", (unsigned)err); /* Now we have the DOM tree in doc3 which represent the Diff */ ... } XmlFreeDocument(xctx, doc1); XmlFreeDocument(xctx, doc2); XmlFreeDocument(xctx, doc3); XmlDestroy(xctx);
8.2.12 出力のカスタマイズ
カスタマイズ済出力ビルダーは、アプリケーションに適したあらゆる形式の差分を格納します。XmlDiff
によって生成され、Xdiff
スキーマに準拠したデフォルトのXdiff
インスタンス・ドキュメントを使用するかわりに、ユーザー自身のカスタマイズ済出力ビルダーを作成できます。
カスタマイズ済出力ビルダーを作成するには、XmlDiff
が差分を決定した後にコールされるコールバックを提供する必要があります。差分はxmdlfop
の配列としてコールバックに渡されます。差分が生成されるたびに、コールバックが呼び出される場合があります。
XPath
生成に必要な内部状態の保守が不要なため、カスタマイズ済出力ビルダーを使用する方が、デフォルトを使用するパフォーマンスが向上する場合があります。
デフォルトでは、XmlDiff
はXdiff
スキーマに準拠するXMLでの差分を検出します。必要な場合は、出力ビルダーをプラグインしてください。差分は配列xmldfop
として表示されます。出力ビルダーのコールバック関数を書き込む必要があります。関数署名は次のとおりです。
xmlerr(*xdfobcb)(void *uctx, xmldfop *escript, ub4 escript_siz);
uctx
は、ユーザー指定のコンテキストです。
escript
は、サイズescript_siz
の配列です。
diff[escript_siz]
mctx
は、メモリー・コンテキストです。
プロパティを介してこのメモリー・コンテキストをXmlDiff()
に提供します。このメモリー・コンテキストを使用して、escript
に割り当てます。後でescript
を解放する必要があります。
XmlDiff()
の起動が戻る前でも発生する差分が検出されたら、出力ビルダーのコールバックを起動します。出力ビルダーのコールバックは、複数回コールされます。
例8-5 カスタマイズ済XMLDiff出力
/* Sample useage: */ ... #include <orastruc.h> / * for 'oraprop' * / ... static oraprop diff_props[] = { ORAPROP(XMLDF_PROPN_CUSTOM_OB, XMLDF_PROPI_CUSTOM_OB, POINTER), ORAPROP(XMLDF_PROPN_CUSTOM_OBMCX, XMLDF_PROPI_CUSTOM_OBMCX, POINTER), ORAPROP(XMLDF_PROPN_CUSTOM_OBUCX, XMLDF_PROPI_CUSTOM_OBUCX, POINTER), { NULL } }; ... oramemctx *mymemctx; ... xmlerr myob(void *uctx, xmldfop *escript, ub4 escript_siz) { /* process diff which is available in escript * / /* free escript - the caller has to do this * / OraMemFree(mymemctx, escript); } main() { ... myctxt *myctx; diff_props[0].value_oraprop.p_oraprop_v = myob; diff_props[1].value_oraprop.p_oraprop_v = mymemctx; diff_props[2].value_oraprop.p_oraprop_v = myctx; XmlDiff(xctx, &err, 0, doc1, NULL, 0, doc2, NULL, 0, diff_props); ...
8.3 XmlPatchの使用
XmlPatch
は、XmlDiff
によって生成されたものまたは別のメカニズムにより作成されたもののいずれかのXdiff
インスタンス・ドキュメントを受け取り、Xdiff
インスタンス・ドキュメント内の指示に従って、他のXML文書を修正します。
8.3.1 XmlPatchコマンドライン・ユーティリティの使用
ユーティリティXmlPatch
のコマンドライン・オプションについて説明します。
表8-3 XmlPatch for Cコマンドライン・オプション
オプション | 説明 |
---|---|
|
デフォルトの入力ファイルのエンコーディングを指定します。XMLファイルでエンコーディングが指定されていない場合、このエンコーディングは入力対象とみなされます。 |
|
出力/データのエンコーディングを指定します。DOMおよびパッチ文書はこのエンコーディングで作成されます。デフォルトはUTF-8です。 |
|
ファイル名をURLとして解析します。 |
|
使用方法のヘルプを表示します。 |
8.3.2 アプリケーションでのXmlPatchの使用
XmlPatch
は、入力文書およびdiff
文書のソース・タイプおよび場所を引数とします。ソース・タイプは、URL、ファイル、orastream
およびstream
コンテキスト・ポインタ、バッファ、buffer_length
ポインタ、またはDOM文書要素(docelement
)へのポインタです。
関連項目:
XmlPatch
の動作を制御するフラグのC APIの詳細は、『Oracle Database XML C APIリファレンス』を参照してください
Xdiff
スキーマによって設定されたモードはXmlPatch
の作業に影響します。
output-model
がSnapshot
の場合、XmlPatch
は、operations-in-docorder
がTRUE
の場合のみ作業します。
output-model
がCurrent
の場合、operations-in-docorder
をTRUE
に設定する必要はありません。
例8-6 XmlPatchに関するサンプル・アプリケーション
... #include <xmldf.h> ... xmlctx *xctx; xmldocnode *doc1, *doc2; oratext *s; oratext *inp1 = "book1.xml"; /* input document */ oratext *inp2 = "diff.xml", /* diff document */ xmlerr err; /* create XML meta context */ if (!(xctx = XmlCreate(&err, (oratext *) "XmlPatch", NULL))) { printf("Failed to create XML context, error %u\n", (unsigned) err); err_exit("Exiting"); } /* Load the two input files */ if (!(doc1 = XmlLoadDom(xctx, &err, "file", inp1, "discard_whitespace", TRUE, NULL))) { printf("Parsing first file failed, error %u\n", (unsigned)err); err_exit((oratext *)"Exiting."); } if (!(doc2 = XmlLoadDom(xctx, &err, "file", inp2, "discard_whitespace", TRUE, NULL))) { printf("Parsing second file failed, error %u\n", (unsigned)err); err_exit((oratext *)"Exiting."); } /* call XmlPatch */ if(!XmlPatch(xctx, &err, 0, XMLDF_SRCT_DOM, doc1, NULL, XMLDF_SRCT_DOM, doc2, NULL, NULL)); printf("XmlPatch Failed, error %u\n", (unsigned)err); else { if(err != XMLERR_OK) printf("XmlPatch returned error %u\n", (unsigned)err); /* Now we have the patched document in doc1 */ ... } XmlFreeDocument(xctx, doc1); XmlFreeDocument(xctx, doc2); XmlDestroy(xctx);
8.4 XmlHashの使用
XmlHash
は、XMLツリーのハッシュ値を計算します。2つのツリーのハッシュ値が同じである場合、それらは同じXMLである可能性が非常に高くなります。XmlHash
を使用すると、XMLツリーがすでにデータベース内にあるかどうかを調べるためにすばやく比較できます。
必要な場合、一致がある可能性がある一致に対してXmlDiff
を再度実行できます。新規文書のハッシュ値を計算して、データベースに問合せを実行できます。
例8-7に、XmlHash
を使用するサンプル・プログラムを示します。
例8-7 XmlHashプログラム
sword main(sword argc, char *argv[])
{
xmlctx *xctx;
xmldfsrct srct;
oratext *data_encoding, *input_encoding, *s, *inp1;
ub1 flags;
xmlerr err;
ub4 num_args;
xmlhasht digest;
flags = 0; /* defaults */
srct = XMLDF_SRCT_FILE;
inp1 = "somexml.xml";
xctx = XmlCreate(&err, (oratext *) "XmlHash", NULL);
if (!xctx)
{
/* handle error with creating xml context and exit */
...
}
/* run XmlHash */
err = XmlHash(xctx, &digest, 0, srct, inp1, NULL, NULL);
if(err)
printf("XmlHash returned error:%d \n", err);
else
txdfha_pd(digest);
XmlDestroy(xctx);
return (sword )err;
}
/* print bytes in xml hash */
static void txdfha_pd(xmlhasht digest)
{
ub4 i;
for(i = 0; i < digest.l_xmlhasht; i++)
printf("%x ", digest.d_xmlhasht[i]);
printf("\n");
}
8.4.1 XmlDiffおよびXmlPatchの起動
XmlDiff
およびXmlPatch
は、コマンドライン・ツールとして、およびC言語からコールされます。SQL関数として使用可能です。
関連項目:
-
『Oracle Database SQL言語リファレンス』の
XMLDiff
に関する項 -
『Oracle Database SQL言語リファレンス』の
XMLPatch
に関する項