23 Cを使用したXML差分の検出

2つのExtensible Markup Language (XML)入力間の差分を求め、差分を一方のXML文書に適用する方法について説明します。

トピック:

23.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つのツリーまたはサブツリー間のハッシュ値が同数の場合、これらのツリーは非常に高い確率で同一です。

トピック:

23.1.1 XMLDiffのプロセス・フロー

XMLDiffのプロセス・フローについて説明します。

  1. XmlDiffを使用して2つの入力文書を比較します。

  2. XmlDiffにより、Xdiffインスタンス・ドキュメントが作成されます。

  3. 必要に応じて、Xdiffインスタンス・ドキュメントをXmlPatchに渡すことができます。

  4. XmlPatchを使用して、比較によって検出された差分を指定した他のドキュメントに適用できます。

23.2 XmlDiffの使用

XmlDiffは、2つの入力文書を示すツリーを比較して差分を検出します。この2つの入力文書では、同一のキャラクタ・セット・エンコーディングを使用する必要があります。Xdiff(出力)インスタンス・ドキュメントには、入力文書のデータ・エンコーディング(DOMエンコーディング)と同一のエンコーディングが含まれます。

トピック:

23.2.1 比較の最適化に関するユーザー・オプション

比較に関する最適化オプションとして、グローバル最適化とローカル最適化の2つがあります。

  • グローバル最適化(デフォルト)

    文書ツリー全体が比較されます。

  • ローカル最適化

    兄弟関係のレベルで比較が行われます。ローカル最適化では、2つのツリーの対応する親の下にある兄弟関係が比較されます。

グローバル最適化では、大きな文書に対してより多くの時間および領域を使用できますが、生成されるのは常に最小の差分セット(最適差分)です。ローカル最適化の方が処理速度は速いですが、最適差分は生成されない場合があります。

23.2.2 ハッシュに関するユーザー・オプション

一般的に、ハッシュによりグローバル最適化が早くなりますが、質が若干落ちる可能性もあります。ローカル最適化では、ハッシュにより差分出力の質が改善されます。異なるハッシュのレベルを使用すると、ローカル差分およびグローバル差分の両方が生成される可能性があります。ローカルおよびグローバルの両方の最適化に関するハッシュの使用を指定できます。

ハッシュを指定するには、hashLevelパラメータを入力します。hashLevelが1より大きい場合、DOMHash値を使用して、差分がdepth >= hashLevelのすべてのサブツリーを比較できます。ハッシュ値が同一の場合は、サブツリーも同一と推定されます。

23.2.3 XmlDiffでの入力文書の見方

XmlDiffでの入力文書の処理方法について説明します。

XmlDiffは、比較の実行中、属性順に差分を無視します。

XmlDiffDocType宣言を無視します。ファイルはDocument Type Definition (DTD)に対して検証されません。

名前空間の接頭辞が同一の名前空間Universal Resource Identifier (URI)を参照する場合は、XmlDiffは名前空間の接頭辞における差分を無視します。それ以外の場合で、2つのノードに同じローカル名および内容が含まれていて名前空間URIが異なる場合は、差分が明示されます。

注意:

XmlDiffは入力文書上で、スキーマに基づかない方法で動作します。要素または属性上で、型を認識する方法では動作しません。

23.2.4 XmlDiffコマンドライン・ユーティリティの使用

ユーティリティXmlDiffのコマンドライン・オプションについて説明します。

表23-1 C言語に関するXmlDiffコマンドライン・オプション

オプション 説明

-e encoding

デフォルトの入力ファイルのエンコーディングを指定します。XMLファイルでエンコーディングが指定されていない場合、このエンコーディングは入力対象とみなされます。

-E encoding

出力/データのエンコーディングを指定します。DOMおよびXdiffインスタンス・ドキュメントはこのエンコーディングで作成されます。デフォルトは8ビット・エンコーディングのUnicode (UTF-8)です。

-h hashLevel

ハッシュのレベルを指定します。0レベルがないことを意味します。

1より大きい場合、サブツリーにハッシュを使用します。

-g

グローバル最適化(デフォルト)を設定します。

-l

ローカル最適化を設定します。

-p

使用方法のヘルプを表示します。

-u

更新操作を無効にします。

23.2.5 入力文書のサンプル

入力XML文書のサンプルを示します。

例23-1は、XmlDiffおよびXmlPatchの使用による更新を説明するXML文書のサンプルです。いくつかの変更が続きます。

次のアクションが結果的に発生すること以外は、例23-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つ)。

例23-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>

23.2.6 Xdiffインスタンス・ドキュメントのサンプル

Xdiffインスタンス・ドキュメントのサンプルを示します。

この項では、前の項で説明された2つのXMLファイルの比較により生成されたXdiffインスタンス・ドキュメントを示します。次の項では、XML処理命令およびこの文書での操作について説明します。

次のようにしてXmlDiffを起動します。

> xmldiff book1.xml book2.xml

この表では、引数およびフラグに関するサンプル・アプリケーションについても見ることができます。

例23-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>

23.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-docordertrueに設定され、XPathが単純である場合のみ、XmlPatchはこのモデルの処理を実行できます。単純なXPathは子の軸をワイルド・カードなしで要求し、述語の位置を/root[1]/child[2]/text()[2]のように使用する必要があります。

    • current: 各操作は、前の操作までのすべての操作が入力文書に適用されているようにXPathを使用します。XmlDiffが差分を現在のモデルで生成しない場合でも、XmlPatchは手作業で作成したdiff文書を現在のモデルで処理できます。

  • diff-algorithm: このオプションはどの最適化が差分を生成するかを示します。

    • グローバル最適化

    • ローカル最適化

23.2.8 Xdiff操作

XmlDiffは、Xdiffインスタンス・ドキュメントによって明示される操作を使用して差分を検出します。XmlDiff操作について説明します。

表23-2 Xdiff操作の属性

属性 説明

parent-pathまたはxpath

オペランド・ノードの親ノードのXPATHの位置またはノードのXPATHの位置を指定します。

node-type

オペランド・ノードのタイプを指定します。

content

追加または挿入される新規のサブツリーまたは値を指定する子要素です。

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インスタンス・ドキュメントを完全に手書きで入力することも可能です。更新操作に関わる要素のすべての子は削除されます。内容ノードで指定された新規のサブツリーは、すべてインポートされます。

23.2.9 Xdiffインスタンス・ドキュメントの形式

XmlDiffの出力であるXdiffインスタンス・ドキュメントは、Xdiff XMLスキーマに準拠するXML文書です。出力文書には、2つの入力文書間の差分を示す一連の操作が含まれます。最初の文書に差分を適用する場合は、2番目の文書を取得します。

23.2.10 Xdiffスキーマ

Xdiffインスタンス・ドキュメント(出力)が従うXdiff XMLスキーマを示します。

例23-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>

23.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リファレンス』を参照してください

例23-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);

23.2.12 カスタマイズ済出力

カスタマイズ済出力ビルダーは、アプリケーションに適したあらゆる形式の差分を格納します。XmlDiffによって生成され、Xdiffスキーマに準拠したデフォルトのXdiffインスタンス・ドキュメントを使用するかわりに、ユーザー自身のカスタマイズ済出力ビルダーを作成できます。

カスタマイズ済出力ビルダーを作成するには、XmlDiffが差分を決定した後にコールされるコールバックを提供する必要があります。差分はxmdlfopの配列としてコールバックに渡されます。差分が生成されるたびに、コールバックが呼び出される場合があります。

XPath生成に必要な内部状態の保守が不要なため、カスタマイズ済出力ビルダーを使用する方が、デフォルトを使用するパフォーマンスが向上する場合があります。

デフォルトでは、XmlDiffXdiffスキーマに準拠するXMLでの差分を検出します。必要な場合は、出力ビルダーをプラグインしてください。差分は配列xmldfopとして表示されます。出力ビルダーのコールバック関数を書き込む必要があります。関数署名は次のとおりです。

xmlerr(*xdfobcb)(void *uctx, xmldfop *escript, ub4 escript_siz);

uctxは、ユーザー指定のコンテキストです。

escriptは、サイズescript_sizの配列です。

diff[escript_siz]

mctxは、メモリー・コンテキストです。

プロパティを介してこのメモリー・コンテキストをXmlDiff()に提供します。このメモリー・コンテキストを使用して、escriptに割り当てます。後でescriptを解放する必要があります。

XmlDiff()の起動が戻る前でも発生する差分が検出されたら、出力ビルダーのコールバックを起動します。出力ビルダーのコールバックは、複数回コールされます。

例23-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);
 ...
 

23.3 XmlPatchの使用

XmlPatchは、XmlDiffによって生成されたものまたは別のメカニズムにより作成されたもののいずれかのXdiffインスタンス・ドキュメントを受け取り、Xdiffインスタンス・ドキュメント内の指示に従って、他のXML文書を修正します。

トピック:

23.3.1 XmlPatchコマンドライン・ユーティリティの使用

ユーティリティXmlPatchのコマンドライン・オプションについて説明します。

表23-3 XmlPatch for Cコマンドライン・オプション

オプション 説明

-eエンコーディング

デフォルトの入力ファイルのエンコーディングを指定します。XMLファイルでエンコーディングが指定されていない場合、このエンコーディングは入力対象とみなされます。

-Eエンコーディング

出力/データのエンコーディングを指定します。DOMおよびパッチ文書はこのエンコーディングで作成されます。デフォルトはUTF-8です。

-i

ファイル名をURLとして解析します。

-h

使用方法のヘルプを表示します。

23.3.2 アプリケーションでのXmlPatchの使用

XmlPatchは、入力文書およびdiff文書のソース・タイプおよび場所を引数とします。ソース・タイプは、URL、ファイル、orastreamおよびstreamコンテキスト・ポインタ、バッファ、buffer_lengthポインタ、またはDOM文書要素(docelement)へのポインタです。

関連項目:

XmlPatchの動作を制御するフラグのC APIの詳細は、『Oracle Database XML C APIリファレンス』を参照してください

Xdiffスキーマによって設定されたモードはXmlPatchの作業に影響します。

output-modelSnapshotの場合、XmlPatchは、operations-in-docorderTRUEの場合のみ作業します。

output-modelCurrentの場合、operations-in-docorderTRUEに設定する必要はありません。

例23-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);

23.4 XmlHashの使用

XmlHashは、XMLツリーのハッシュ値を計算します。2つのツリーのハッシュ値が同じである場合、それらは同じXMLである可能性が非常に高くなります。XmlHashを使用すると、XMLツリーがすでにデータベース内にあるかどうかを調べるためにすばやく比較できます。

必要な場合、一致がある可能性がある一致に対してXmlDiffを再度実行できます。新規文書のハッシュ値を計算して、データベースに問合せを実行できます。

例23-7に、XmlHashを使用するサンプル・プログラムを示します。

例23-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");
}

トピック:

23.4.1 XmlDiffおよびXmlPatchの起動

XmlDiffおよびXmlPatchは、コマンドライン・ツールとして、およびC言語からコールされます。SQL関数として使用可能です。

関連項目: