20 XML Parser for Cの使用
Extensible Markup Language (XML) Parser for Cの使用方法について説明します。
トピック:
- XML Parser for Cの概要
このトピックでは、XML Parser for Cの前提条件および標準について説明します。 - XML Parser API for Cの使用
Oracle XML Parser for Cは、XML文書が整形式であるかどうか、およびDTDに対して妥当であるかどうか(オプション)を確認します。アプリケーションでは、DOMまたはSAX APIを使用して、解析されたデータにアクセスできます。 - DOM API for Cの使用
このトピックでは、XML文書のエンコーディングの制御、NULL文字終了および長さエンコードの関数の使用、およびエラーの処理について説明します。 - orastream関数の使用
orastream関数APIは、1つのピースですべて取得するかわりに、大規模なチャンクのデータをノードからストリームするインタフェースです。したがって、64KBより大きいノードにアクセスできます。 - SAX API for Cの使用
SAXを使用するには、xmlsaxcb構造を関数ポインタで初期化し、XmlLoadSax()に渡します。また、各SAX関数に渡す、ユーザー定義コンテキスト構造へのポインタを含めることができます。 - XML Pull Parser for Cの使用
XML Pull Parserは、XMLイベント・インタフェースを実装しています。XML Pull ParserとSAXパーサーは類似していますが、Pull Parserを使用する場合はアプリケーション(コンシューマ)がイベントを駆動する一方、SAXパーサーの場合はパーサー(プロデューサ)がイベントを駆動します。 - OCIおよびXDK for C APIの使用
この項では、Oracle Call Interface (OCI)からのXDK for C関数へのアクセスについて説明します。
20.1 XML Parser for Cの概要
このトピックでは、XML Parser for Cの前提条件および標準について説明します。
トピック:
- XML Parser for Cの使用の前提条件
Oracle XML Parser for CはXML文書を読み取り、DOMまたはSAXアプリケーション・プログラミング・インタフェース(API)を使用してそのコンテンツと構造へのプログラムでのアクセスを提供します。このパーサーは検証モードまたは非検証モードで使用できます。またPull Parserも使用可能です。 - XML Parser for Cの標準および仕様
XDK XMLパーサーの標準および仕様について説明します。
関連項目:
Document Object Model (DOM)およびSimple API for XML (SAX)を使用したXML解析の概要は、「XML Parsing for Javaの概要」を参照してください。概要の大部分の情報は特定の言語に依存しておらず、Cにも適用されます。
20.1.1 XML Parser for Cの使用の前提条件
Oracle XML Parser for CはXML文書を読み取り、DOMまたはSAXアプリケーション・プログラミング・インタフェース(API)を使用してそのコンテンツと構造へのプログラムでのアクセスを提供します。このパーサーは検証モードまたは非検証モードで使用できます。またPull Parserも使用可能です。
この章では、次のテクノロジを十分に理解していると想定します。
-
Document Object Model (DOM): DOMは、XML文書の構造を示すインメモリー・ツリー表現です。
-
Simple API for XML (SAX): SAXは、イベントベースのXML解析の標準です。
-
XML Pull Parser for Cの使用Pull ParserではXMLイベントが使用されます。
-
Document Type Definition (DTD): XML DTDは、XML文書の有効な構造を定義します。
-
XMLスキーマ。DTDと同様にXMLスキーマはXML文書の有効な構造を定義します。
-
XML名前空間。名前空間は、要素名や属性名を区別するためのメカニズムです。
前述のテクノロジの概要説明が必要な場合は、「関連ドキュメント」にあるXMLの資料を参照してください。
20.1.2 XML Parser for Cの標準および仕様
XDK XMLパーサーの標準および仕様について説明します。
-
XML 1.0はW3C勧告です。Oracle XML Developer's Kit (XDK) for C APIはXML 1.0(Second Edition)をフル・サポートしています。
-
DOMレベル1、レベル2およびレベル3の仕様はWorld Wide Web Consortium (W3C)勧告です。XDK for C APIはDOMレベル1および2をフル・サポートしていますが、レベル3はサポートしていません。
-
SAXにはバージョン1.0と2.0があり、バージョン1.0は非推奨です。SAXはW3C仕様ではありません。XDK for C APIはSAX 1.0および2.0の両方をフル・サポートしています。
-
XML名前空間はW3C勧告です。
20.2 XML Parser API for Cの使用
Oracle XML Parser for Cは、XML文書が整形式であるかどうか、およびDTDに対して妥当であるかどうか(オプション)を確認します。アプリケーションでは、DOMまたはSAX APIを使用して、解析されたデータにアクセスできます。
トピック:
- Parser API for Cの概要
XML解析APIの中核は、XML、DOM、SAXの各APIです。 - XML Parser for Cのコール順序
XML Parser for Cのコール順序を示します。 - XML Parser for Cの使用: 基本プロセス
XML Parser for Cの使用の基本プロセスについて説明します。 - XML Parser for Cのデモ・プログラムの実行
$ORACLE_HOME/xdk/demo/c/(UNIXの場合)および%ORACLE_HOME%\xdk\demo\c(Windowsの場合)ディレクトリには、DOMインタフェースおよびSAXインタフェースによるXML Parser for Cの使用方法を示すXMLアプリケーションがあります。 - XML Parser for Cコマンドライン・ユーティリティの使用
$ORACLE_HOME/bin(UNIXの場合)または%ORACLE_HOME%\bin(Windowsの場合)にあるxmlユーティリティは、XML文書を解析するコマンドライン・インタフェースです。XML文書が整形式であるか、および妥当であるかを確認します。
20.2.1 Parser API for Cの概要
XML解析APIの中核は、XML、DOM、SAXの各APIです。
表20-1に、これらのAPIのインタフェースを示します。APIドキュメントの詳細は、『Oracle Database XML C APIリファレンス』を参照してください。
表20-1 XML、DOM、SAXの各APIのインタフェース
| パッケージ | インタフェース | 関数名の表記規則 |
|---|---|---|
|
XML |
このパッケージは、1つの
|
関数名は文字列 APIドキュメントについては、『Oracle Database XML C APIリファレンス』を参照してください。 |
|
DOM |
このパッケージは、解析済XMLへのプログラム・アクセスを提供します。このパッケージは次のインタフェースを実装します。
|
関数名は文字列 APIドキュメントについては、『Oracle Database XML C APIリファレンス』を参照してください。 |
|
SAX |
このパッケージは、解析済XMLへのプログラム・アクセスを提供します。このパッケージは、SAXイベントの通知を受け取る関数を定義する |
関数名は文字列 APIドキュメントについては、『Oracle Database XML C APIリファレンス』を参照してください。 |
|
XML Pull Parser |
XMLイベントとはXML文書の表現で、開始タグ、終了タグ、コメントなどのような一連のイベントで文書が表現されるSAXイベントに類似しています。SAXイベントはパーサー(生産者)によって駆動され、XMLイベントはアプリケーション(消費者)によって駆動されるという点で異なります。 |
関数名は文字列 APIドキュメントについては、『Oracle Database XML C APIリファレンス』を参照してください。 |
トピック:
- XML Parser for Cのデータ型
XML Parser for Cで使用するデータ型について説明します。 - XML Parser for Cのデフォルト
XML Parser for Cのデフォルトについて説明します。
20.2.1.1 XML Parser for Cのデータ型
XML Parser for Cで使用するデータ型について説明します。
XDK for Cのデータ型の完全なリストは、『Oracle Database XML C APIリファレンス』を参照してください。
表20-2 XML Parser for Cで使用するデータ型
| データ型 | 説明 |
|---|---|
|
|
文字列ポインタ |
|
|
マスターXMLのコンテキスト |
|
|
SAXコールバック構造(SAXのみ) |
|
|
32ビット以上の符号なし整数 |
|
|
ネイティブな符号なし整数 |
20.2.1.2 XML Parser for Cのデフォルト
XML Parser for Cのデフォルトについて説明します。
デフォルトは次のとおりです。
-
キャラクタ・セット・エンコーディングは8ビット・エンコーディングのUnicode (UTF-8)です。ドキュメントがすべてASCII形式である場合は、パフォーマンス向上のために、エンコーディングをUS-ASCIIに設定することをお薦めします。
-
パーサーのメッセージは、エラー・ハンドラが提供されていないかぎり、
stderrに出力されます。 -
パーサーは入力文書が整形式であるかどうかを確認しますが、妥当であるかどうかは確認しません。プロパティ"validate"を設定することで、入力の妥当性を検証できます。
注意:
シングルバイト・キャラクタ・セット(US-ASCII、ISO 8859キャラクタ・セットのいずれかなど)のみを使用している場合、明示的にデフォルトのエンコーディングを設定することをお薦めします。UTF-8などのマルチバイト・キャラクタ・セットを使用した場合よりパフォーマンスが向上します。
-
空白を処理する際、パーサーはXML 1.0仕様に準拠します。つまり、パーサーは空白をすべてアプリケーションに報告しますが、無視できる空白を示します。ただし、アプリケーションによっては空白文字の破棄プロパティを設定し、要素の終了タグと次の要素の開始タグの間のすべての空白を破棄する場合もあります。
関連項目:
-
DOM、SAX、Pull ParserおよびコールバックのAPIの詳細は、『Oracle Database XML C APIリファレンス』を参照してください。
20.2.3 XML Parser for Cの使用: 基本プロセス
XML Parser for Cの使用の基本プロセスについて説明します。
アプリケーションで次の手順を実行します。
独自のメモリー割当てにはメモリー・コールバック関数XML_ALLOC_FおよびXML_FREE_Fを使用できます。その場合、両方の関数を指定します。
20.2.4 XML Parser for Cのデモ・プログラムの実行
$ORACLE_HOME/xdk/demo/c/(UNIXの場合)および%ORACLE_HOME%\xdk\demo\c(Windowsの場合)ディレクトリには、DOMインタフェースおよびSAXインタフェースによるXML Parser for Cの使用方法を示すXMLアプリケーションがあります。
表20-3に、デモを示します。
makeユーティリティでは、ソース・ファイルfileName.cをコンパイルし、デモ・プログラムfileNameおよび出力ファイルfileName.outを作成できます。予期される出力は、fileName.stdです。
表20-3 Cパーサーのデモ
| ディレクトリ | 内容 | デモ |
|---|---|---|
|
|
DOMNamespace.c DOMSample.c FullDom.c FullDom.xml NSExample.xml Traverse.c XPointer.c class.xml cleo.xml pantry.xml |
次のデモ・プログラムではDOM APIを使用します。
|
|
|
NSExample.xml SAXNamespace.c SAXSample.c cleo.xml |
次のデモ・プログラムではSAX APIを使用します。
|
サンプル・プログラムのコンパイルおよび実行方法を説明するドキュメントは、同じディレクトリ内のREADMEにあります。この場合、基本的な手順は次のようになります。
-
ディレクトリを
$ORACLE_HOME/xdk/demo/c(UNIXの場合)または%ORACLE_HOME%\xdk\demo\c(Windowsの場合)に変更します。 -
「UNIXでのXDK for C環境変数の設定」および「WindowsでのXDK for C環境変数の設定」の説明に従って、環境変数が設定されていることを確認します。
-
システム・プロンプトで
make(UNIXの場合)またはMake.bat(Windowsの場合)を実行します。makeユーティリティでは、ディレクトリを各デモ・サブディレクトリに変更し、makeを実行して次の処理を行います。-
ccユーティリティでCソース・ファイルをコンパイルします。たとえば、$ORACLE_HOME/xdk/demo/c/domディレクトリのMakefileには、次の行があります。$(CC) -o DOMSample $(INCLUDE) $@.c $(LIB)
-
各デモ・プログラムを実行し、出力をファイルにリダイレクトします。たとえば、
$ORACLE_HOME/xdk/demo/c/domディレクトリのMakefileには、次の行があります。./DOMSample > DOMSample.out
-
-
プログラムごとに
*.stdファイルと*.outファイルを比較します。*.stdファイルには、各プログラムの予期される出力が入っています。たとえば、DOMSample.stdには、DOMSampleの実行で予期される出力が入っています。
20.2.5 XML Parser for Cコマンドライン・ユーティリティの使用
$ORACLE_HOME/bin (UNIXの場合)または%ORACLE_HOME%\bin (Windowsの場合)にあるxmlユーティリティは、XML文書を解析するコマンドライン・インタフェースです。XML文書が整形式であるか、および妥当であるかを確認します。
xmlを使用するには、「UNIXでのXDK for C環境変数の設定」および「WindowsでのXDK for C環境変数の設定」の説明に従って、環境が設定されていることを確認します。
コマンドラインで次の構文を使用して、xmlを起動します。Windowsではxml.exeを使用します。
xml [options] [document URI] xml -f [options] [document filespec]
表20-4に、コマンドライン・オプションを示します。
表20-4 C XML Parserのコマンドライン・オプション
| オプション | 説明 |
|---|---|
|
|
XSLTプロセッサのベースURIを設定します。 |
|
|
入力文書が整形式であるかどうかを確認しますが、妥当であるかどうかは確認しません。 |
|
|
デフォルトの入力ファイルのエンコーディング(インコーディング)を指定します。 |
|
|
DOM/SAXのエンコーディング(アウトコーディング)を指定します。 |
|
|
ファイルをURIではなくfilespecとして解析します。 |
|
|
ファイルに指定された |
|
|
使用方法のヘルプおよびコマンドライン・オプションの基本リストを表示します。 |
|
|
コマンドライン・オプションの詳細なリストを表示します。 |
|
|
|
|
|
エラー報告用の言語を指定します。 |
|
|
DOMを検索し、要素の数を報告します。次に、出力例を示します。 ELEMENT 1
PCDATA 1
DOC 1
TOTAL 3 * 60 = 180 |
|
|
|
|
|
解析後の文書/DTDの構造を出力します。たとえば、ルート要素 +---ELEMENT greeting
+---PCDATA "hello" |
|
|
ルート要素から文書を出力します。たとえば、ルート要素 <greeting>hello</greeting> |
|
|
ルート・ノード(DOC)からXML宣言を含めて出力します。 |
|
|
|
|
|
出力にXML宣言を含めます。 |
|
|
|
|
|
XDKパーサーのバージョンを表示した後、終了します。 |
|
|
|
|
|
空白をすべて保持します。 |
|
|
警告の後で解析を停止します。 |
|
|
SAXインタフェースを実行し、文書を出力します。次に出力例を示します。 StartDocument
XMLDECL version='1.0' encoding=FALSE
<greeting>
"hello"
</greeting>
EndDocument |
トピック:
- XML Parser for Cコマンドライン・ユーティリティの使用: 例
$ORACLE_HOME/xdk/demo/cにある様々なXMLファイルに対してxml文書をテストできます。
20.2.5.1 XML Parser for Cコマンドライン・ユーティリティの使用: 例
$ORACLE_HOME/xdk/demo/cにある様々なXMLファイルに対してxml文書をテストできます。
例20-1に、NSExample.xmlの内容を示します。
次の例に示すように、このファイルを解析し、要素数を計算し、DOMツリーを表示できます。
xml -np NSEample.xml > xml.out
例20-2に出力を示します。
例20-1 NSExample.xml
<!DOCTYPE doc [
<!ELEMENT doc (child*)>
<!ATTLIST doc xmlns:nsprefix CDATA #IMPLIED>
<!ATTLIST doc xmlns CDATA #IMPLIED>
<!ATTLIST doc nsprefix:a1 CDATA #IMPLIED>
<!ELEMENT child (#PCDATA)>
]>
<doc nsprefix:a1 = "v1" xmlns="http://www.w3c.org"
xmlns:nsprefix="http://www.oracle.com">
<child>
This element inherits the default Namespace of doc.
</child>
</doc>
例20-2 xml.out
ELEMENT 2
PCDATA 1
DOC 1
DTD 1
ELEMDECL 2
ATTRDECL 3
TOTAL 10 * 112 = 1120
+---ELEMENT doc [nsprefix:a1='v1'*, xmlns='http://www.w3c.org'*, xmlns:nsprefix=
'http://www.oracle.com'*]
+---ELEMENT child
+---PCDATA "
This element inherits the default Namespace of doc.
"20.3 DOM API for Cの使用
このトピックでは、XML文書のエンコーディングの制御、NULL文字終了および長さエンコードの関数の使用、およびエラーの処理について説明します。
トピック:
- C APIに対応するXML文書のデータ・エンコーディングの制御
XMLデータは多くのエンコーディングに存在します。XMLエンコーディングは様々な方法で制御できます。 - NULL文字終了および長さエンコードのC API関数の使用
Cにおけるネイティブな文字列表現はNULL文字で終了します。そのため、プライマリDOMインタフェースではNULL文字で終了する文字列が使用され、戻されます。ただし、Oracle XML DB dataデータが表形式で格納されている場合、NULLで終了するのではなく、長さがエンコードされます。したがって、XDKでは、頻度の高い場合にパフォーマンスを向上させるために、長さエンコードAPIの追加セットが提供されます。 - C APIを使用したエラー処理
C API関数では、通常、数値のエラー・コード(成功の場合は0 (ゼロ)、失敗の場合は0 (ゼロ)以外)が戻されるか、または変数によりエラー・コードが戻されます。いずれの場合も、APIによってエラー・コードが格納されます。アプリケーションでは、XmlDomGetLastError()関数を起動して、最新のエラーを取得できます。
20.3.1 C APIに対応するXML文書のデータ・エンコーディングの制御
XMLデータは多くのエンコーディングに存在します。XMLエンコーディングは様々な方法で制御できます。
-
自己記述的でないファイルに対して前提とするデフォルト・エンコーディングの指定
-
DOMまたはSAXの表示用エンコーディングの指定
-
DOMがシリアライズされている場合の再エンコーディング
入力XMLデータは常にエンコードされています。16ビット・エンコーディングのUnicode (UTF-16)など、エンコーディングによっては完全に自己記述的なものがあり、この場合は実際のデータの開始前に特定のバイト・オーダー・マーク(BOM)が必要です。XMLDeclまたは文書のMultipurpose Internet Mail Extensions (MIME)ヘッダーでもエンコーディングを指定できます。アプリケーションで特定のエンコーディングを決定できない場合、デフォルトの入力エンコーディングが適用されます。デフォルトを指定していない場合、ASCIIプラットフォームではUTF-8、EBCDICプラットフォームではUTF-EBCDICが想定されます。
APIでは、入力文書のエンコーディング・データが不正である場合に備えて、対策が取られています。たとえば、encoding=asciiと記述されているXMLDeclが含まれるASCII文書がEBCDICに変換されたとします。新しいEBCDIC文書には、(EBCDIC内に)文書がASCIIであると誤って主張するXMLDeclが含まれます。XMLデータを再エンコードするプログラムの正しい動作は、XMLDeclの変換ではなく、これを再生成することです。XMLDeclは、データそのものではなく、メタデータです。しかし、このルールは無視されることが多く、そのため不正な文書が生成されます。この問題を回避するため、APIには入力エンコーディングの強制的な設定を可能にする追加フラグが提供されており、不正なXMLDeclの問題が解決されています。
入力エンコーディングを決定するための優先順位ルールは、次のとおりです。
アプリケーションでは、入力エンコーディングが決定された後、ドキュメントの解析およびデータの表示が可能になります。表示用エンコーディングを選択できます。元の入力エンコーディングにかかわらず、データにはこの表示用エンコーディングが実行されます。
アプリケーションでシリアライズ形式でDOMを書き戻す時点で、表示用データの再エンコードを選択できます。したがって、シリアライズされた文書を任意のエンコーディングにすることができます。
20.3.2 NULL文字終了および長さエンコードのC API関数の使用
Cにおけるネイティブな文字列表現はNULL文字で終了します。そのため、プライマリDOMインタフェースではNULL文字で終了する文字列が使用され、戻されます。ただし、Oracle XML DB dataデータが表形式で格納されている場合、NULLで終了するのではなく、長さがエンコードされます。したがって、XDKでは、頻度の高い場合にパフォーマンスを向上させるために、長さエンコードAPIの追加セットが提供されます。
特に、表20-5のDOM関数には2つのAPIがあります。
表20-5 NULL文字終了および長さエンコードのC API関数
| NULL文字終了API | 長さエンコードAPI |
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
20.4 orastream関数の使用
orastream関数APIは、1つのピースですべて取得するかわりに、大規模なチャンクのデータをノードからストリームするインタフェースです。したがって、64KBより大きいノードにアクセスできます。
orastream APIは、汎用入力または出力ストリームを表します。XDKユーザーはxml.hを介して、このインタフェースを使用します。これは、このインタフェースを実装するorastreamデータ構造および関数のセットにより定義されます。ストリームの作成者は、ストリーム関数アドレスのリストおよびストリーム・コンテキストをOraStreamInitに渡します。この関数は、orastream構造のインスタンスを戻します。
初期化の時点で、複数のストリーム・プロパティを指定します。読取りまたは書込みが指定された場合、ストリームはOraStreamRead()およびOraStreamWrite()を使用してバイト・モードで動作します。"read_char"または"write_char"が指定された場合、ストリームはOraStreamReadChar()およびOraStreamWriteChar()を使用してキャラクタ・モードで動作します。キャラクタ・モードの場合、完全な文字のみを読み込みまたは書き込み、バッファ境界を越えて分割しません。
ストリーム・コンテキストは、orastreamの状態を表すのに使用され、ストリームの存続期間中、存続します。
Javaの入力または出力ストリームと同様、常に、データのソースまたはシンクを指定します。出力ストリームはデータを移入する外部ストリームまたはオブジェクトのアドレスを格納します。同様に、入力ストリームは読み込まれるオブジェクトのアドレスを格納します。
次に、orastream関数の例を示します。
struct orastream; typedef struct orastream orastream; typedef ub4 oraerr; /* Error code: zero is success, non-zero is failure */
/* Initialize (Create) & Destroy (Terminate) stream object */
orastream *OraStreamInit(void *sctx, void *sid, oraerr *err, ...);
oraerr OraStreamTerm(orastream *stream);
/* Set or Change SID (streamID) for stream (returns old stream ID through osid)*/
oraerr OraStreamSid(orastream *stream, void *sid, void **osid);
/* Is a stream readable or writable? */
boolean OraStreamReadable(orastream *stream);
boolean OraStreamWritable(orastream *stream);
/* Open & Close stream */
oraerr OraStreamOpen(orastream *stream, ubig_ora *length);
oraerr OraStreamClose(orastream *stream);
/* Read | Write byte stream */
oraerr OraStreamRead(orastream *stream, oratext *dest, ubig_ora size,
oratext **start, ubig_ora *nread, ub1 *eoi);
oraerr OraStreamWrite(orastream *stream, oratext *src, ubig_ora size,
ubig_ora *nwrote);
/* Read | Write char stream */
oraerr OraStreamReadChar(orastream *stream, oratext *dest, ubig_ora size,
oratext **start, ubig_ora *nread, ub1 *eoi);
oraerr OraStreamWriteChar(orastream *stream, oratext *src, ubig_ora size,
ubig_ora *nwrote);
/* Return handles for stream */
orastreamhdl *OraStreamHandle(orastream *stream);
/* Returns status: if the stream object is currently opened or not */
boolean OraStreamIsOpen(orastream *stream);
ストリーム・エラー・コードは次のとおりです。
#define ORASTREAM_ERR_NULL_POINTER 1 /* NULL pointer given */ #define ORASTREAM_ERR_BAD_STREAM 2 /* invalid stream object */ #define ORASTREAM_ERR_WRONG_DECTION 3 /* tried wrong-direction I/O */ #define ORASTREAM_ERR_UNKNOWN_PROPERTY 4 /* unknown creation prop */ #define ORASTREAM_ERR_NO_DIRECTION 5 /* neither read nor write? */ #define ORASTREAM_ERR_BI_DIRECTION 6 /* both read any write? */ #define ORASTREAM_ERR_NOT_OPEN 7 /* stream not open */ #define ORASTREAM_ERR_WRONG_MODE 8 /* wrote byte/char mode */ /* --- Open errors --- */ #define ORASTREAM_ERR_CANT_OPEN 10 /* can't open stream */ /* --- Close errors --- */ #define ORASTREAM_ERR_CANT_CLOSE 20 /* can't close stream */
関連項目:
orastream APIのパラメータ定義などの参考情報は、『Oracle Database XML C APIリファレンス』を参照してください
例20-3 orastream関数の使用
int test_read()
{
xmlctx *xctx = NULL;
oratext *barray, *docName = "NSExample.xml";
orastream* ostream = (orastream *) 0;
xmlerr ecode = 0;
ub4 wcount = 0;
ubig_ora destsize, nread;
oraerr oerr = 0;
ub1 eoi = 0;
nread = destsize = 1024;
if (!(xctx = XmlCreateNew(&ecode, (oratext *)"stream_xctx", NULL, wcount,
NULL)))
{
printf("Failed to create XML context, error %u\n", (unsigned)ecode);
return -1;
}
barray = XmlAlloc(xctx, sizeof(oratext) * destsize);
/* open function should be specified in order to read correctly. */
if (!(ostream = OraStreamInit(NULL,docName, (oraerr *)&ecode,
"open", fileopen,
"read", fileread,
NULL)))
{
printf("Failed to initialize OrsStream, error %u\n",(unsigned)ecode);
return -1;
}
/* check readable and writable */
if (OraStreamReadable(ostream))
printf("ostream is readable\n");
else
printf("ostream is not readable\n");
if (OraStreamWritable(ostream))
printf("ostream is writable\n");
else
printf("ostream is not writable\n");
if (oerr = OraStreamRead(ostream, barray, destsize, &barray, &nread, &eoi))
{
printf("Failed to read due to orastream was not open, error %u\n", oerr);
}
/* open orastream */
OraStreamOpen(ostream, NULL);
/* read document */
OraStreamRead(ostream, barray, destsize, &barray, &nread, &eoi);
OraStreamTerm(ostream);
XmlDestroy(xctx);
return 0;
}
ORASTREAM_OPEN_F(fileopen, sctx, sid, hdl, length)
{
FILE *fh = NULL;
printf("Opening orastream %s...\n", (oratext *)sid);
if (sid && ((fh= fopen(sid, "r")) != NULL))
{
printf("Opening orastream %s...\n", (oratext *)sid);
}
else
{
printf("Failed to open input file.\n");
return -1;
}
/* store file handle generically, NULL means stdout */
hdl->ptr_orastreamhdl = fh;
return XMLERR_OK;
}
ORASTREAM_READ_F(fileread, sctx, sid, hdl,
dest, size, start, nread, eoi)
{
FILE *fh = NULL;
int i =0;
printf("Reading orastream %s ...\n", (oratext *)sid);
// read data from file to dest
if ((fh = (FILE *) hdl->ptr_orastreamhdl) != NULL)
*nread = fread(dest, 1, size, fh);
printf("Read %d bytes from orastream...\n", (int) *nread);
*eoi = (*nread < size);
if (start)
*start = dest;
printf("printing document ...\n");
for(i =0; i < *nread; i++)
printf("%c", (char)dest[i]);
printf("\nend ...\n");
return ORAERR_OK;
}20.5 SAX API for Cの使用
SAXを使用するには、xmlsaxcb構造を関数ポインタで初期化し、XmlLoadSax()に渡します。また、各SAX関数に渡す、ユーザー定義コンテキスト構造へのポインタを含めることができます。
関連項目:
SAXコールバック構造については、『Oracle Database XML C APIリファレンス』を参照してください
20.6 XML Pull Parser for Cの使用
XML Pull Parserは、XMLイベント・インタフェースを実装しています。XML Pull ParserとSAXパーサーは類似していますが、Pull Parserを使用する場合はアプリケーション(コンシューマ)がイベントを駆動する一方、SAXパーサーの場合はパーサー(プロデューサ)がイベントを駆動します。
XML Pull ParserとSAXは両方とも、文書を開始タグ、終了タグおよびコメントのある一連のイベントとして表します。XML Pull Parserは、単純なAPIのセットと基礎となるイベントのセットを公開することによって、アプリケーションに制御を渡します。SAXなどのコールバック内でイベントを処理するのではなく、XmlEvNextのようなメソッドを使用して、アプリケーションは次のイベントをリクエストしたり、または取り出すことができます。そのため、アプリケーションではXML処理においてより手続き的な制御を行います。また、ドキュメント全体を解析するSAXアプリケーションとは異なり、処理を途中で停止することもできます。
トピック:
- 基本的なXML Pull Parsing機能の使用
XML Pull Parserを使用するために必要な手順について説明します。 - 複数のXML文書の解析
XMLイベント・コンテキストを作成して初期化した後、XmlEvLoadPPDocおよびXmlEvCleanPPCtxを繰り返し起動し、複数の文書を解析できます。 - IDコールバック
コールバックを提供して、テキストベースの名前から8バイトの識別子(ID)に変換できます。 - XML Pull Parserのエラー処理
XML Pull Parserのエラー処理について説明します。 - サンプルPull Parserアプリケーション
サンプルPull Parserアプリケーション、解析する文書、および文書から生成されるイベントのリストについて説明します。
20.6.1 基本的なXML Pull Parsing機能の使用
XML Pull Parserを使用するために必要な手順について説明します。
トピック:
- XMLイベント・コンテキスト
XMLイベント・コンテキスト構造を示します。 - XMLイベント・コンテキストの概要
各XML Pull Parserでは、固有のコンテキストの作成および固有のAPI関数の実装が可能です。
20.6.1.1 XMLイベント・コンテキスト
XMLイベント・コンテキスト構造を示します。
例20-4 XMLイベント・コンテキスト
typedef struct {
void *ctx_xmlevctx; /* implementation specific context */
xmlevdisp *disp_xmlevctx; /* dispatch table */
ub4 checkword_xmlevctx; /* checkword for integrity check */
ub4 flags_xmlevctx; /* mode; default: expand_entity */
struct xmlevctx *input_xmlevctx; /* input xmlevctx; chains the XML Event
context */
} xmlevctx;20.6.1.2 XMLイベント・コンテキストの概要
各XML Pull Parserでは、固有のコンテキストの作成および固有のAPI関数の実装が可能です。
-
ディスパッチ表
disp_xmlevctxというディスパッチ表には、XmlEvCreatePPCtx関数、XmlEvCreatePPCtxVA関数、XmlEvDestoryPPCtx関数、XmlEvLoadPPDoc関数、およびXmlEvCleanPPCtx関数を除いて、各API関数に1つのポインタが含まれます。イベント・コンテキストが作成されると、ポインタ
disp_xmlevctxは静的表のアドレスで初期化されます。 -
実装固有のイベント・コンテキスト
フィールド
ctx_xmlevctxは、特定の実装の起動に固有のコンテキストのアドレスで初期化される必要があります。実装固有のイベント・コンテキストは*void型なので、別のアプリケーションとは異なります。 -
入力イベント・コンテキスト
各Pull Parserは、
xmlevctxという入力イベント・コンテキストを指定できます。このフィールドでは、パーサーにより複数のイベント生産者を連鎖させることが可能です。結果として、コンテキストでディスパッチ関数がNULLと指定されている場合、アプリケーションは入力イベント・コンテキストの連鎖にある次のNULL以外のディスパッチ関数を使用します。基本的なxmlevctxでは、すべてのディスパッチ関数のポインタはNULL以外であることを確認する必要があります。
20.6.2 複数のXML文書の解析
XMLイベント・コンテキストを作成して初期化した後、XmlEvLoadPPDocおよびXmlEvCleanPPCtxを繰り返し起動し、複数の文書を解析できます。
XMLイベント・コンテキスト作成中にアプリケーションによって定義されたプロパティは、XmlLoadPPDoc関数への各起動に対して変更できません。プロパティを変更する場合は、イベント・コンテキストを破棄して再作成します。
XmlEvCleanPPCtxにより現行のパーサーの内部構造を削除した後、イベント・コンテキストを再利用して別の文書を分析できます。
20.6.3 IDコールバック
コールバックを提供して、テキストベースの名前から8バイトの識別子(ID)に変換できます。
コールバック関数署名
typedef sb8 (*xmlev_id_cb_funcp)( void *ctx , ub1 type, ub1 *token, ub4 tok_len,
sb8 nmspid, boolean isAttribute);戻り値
sb8は8バイトのIDです。
引数
-
*
ctxはコンテキスト実装です。 -
typeは次の列挙に含まれる型です。typedef enum { XML_EVENT_ID_URI, XML_EVENT_ID_QNAME, }xmlevidtype; -
*
tokenおよびtok_lenは変換される実際のテキストです。 -
nmspidは名前空間IDです。 -
isAttributeは単一の属性を示すブール値です。
XmlEvGetTagIdおよびXmlEvGetAttrID APIは内部的にこのコールバックを2回起動し、1回は名前空間IDをフェッチし、他の1回はタグの実際のIDまたはQname属性をフェッチします。
XmlEvGetTagUriIDおよびXmlEvGetAttrUriID関数はこのコールバックを1回起動し、対応するUniversal Resource Identifier (URI)のIDを取得します。
コールバックが指定されない場合、これらのAPIが使用されるとエラーXML_ERR_EVENT_NOIDCBKが戻されます。
20.6.4 XML Pull Parserのエラー処理
XML Pull Parserのエラー処理について説明します。
トピック:
- パーサー・エラー
パーサーで発生するエラーについて説明します。 - プログラミング・エラー
プログラムのエラーを処理するため、XDKには、アプリケーションがイベント・コンテキスト作成時に指定できるコールバックが用意されています。このコールバックは、アプリケーションが無効なAPIに起動する場合に起動されます。
20.6.4.1 パーサー・エラー
パーサーで発生するエラーについて説明します。
入力文書が不正な形式であるためエラーがスローされると、XML Pull ParserによりXML_EVENT_FATAL_ERRORというメッセージが戻されます。関数XmlEvGetErrorにより、エラー番号およびメッセージが取得されます。
XmlCreate中にアプリケーションによって指定されたエラー処理は、XmlEvCreatePPCtx操作の間、オーバーライドされます。XmlEvDestroyPPCtx操作で元のコールバックをリストアした後、アプリケーションはXmlErrSetHandler関数を起動する必要があります。
20.6.4.2 プログラミング・エラー
プログラムのエラーを処理するため、XDKには、アプリケーションがイベント・コンテキスト作成時に指定できるコールバックが用意されています。このコールバックは、アプリケーションが無効なAPIに起動する場合に起動されます。
コールバックのシグネチャは次のとおりです。
typedef void (* xmlev_err_cb_funcp)(xmlctx *xctx, xmlevctx *evctx,
xmlevtype cur_event);
無効なAPIの起動の例は次のとおりです。
XmlEvGetNameはXML_EVENT_CHARACTERSイベントに対してコールされません。
20.6.5 サンプルPull Parserアプリケーション
サンプルPull Parserアプリケーション、解析する文書、および文書から生成されるイベントのリストについて説明します。
例20-5に、サンプルのアプリケーション・コードを示します。
例20-6に、解析するサンプル文書を示します。
例20-7に、属性イベント・プロパティがFALSEで展開エンティティ・プロパティがTRUEである場合に生成される一連のイベントを示します。
例20-5 サンプルPull Parserアプリケーションの例
# include "xml.h"
# include "xmlev.h"
...
xmlctx *xctx;
xmlevctx *evtcx;
if (!(xctx = XmlCreate(&xerr, (oratext *) "test")))
{
printf("Failed to create XML context, error %u\n", (unsigned) xerr);
return -1;
}
...
if(!(evctx = XmlEvCreatePPCtx(xctx, &xerr, NULL)))
{
printf("Failed to create EVENT context, error %u\n", (unsigned) xerr);
return -1;
}
for(i = 0; i < numDocs; i++)
{
if (xerr = XmlEvLoadPPDoc(xctx, evctx, "file", input_filenames[i], 0, NULL)
{
printf("Failed to load the document, error %u\n", (unsigned) xerr);
return -1;
}
...
for(;;)
{
xmlevtype cur_event;
cur_event = XmlEvNext(evctx);
switch(cur_event)
{
case XML_EVENT_FATAL_ERROR:
XmlEvGetError(evctx, (oratext **)&errmsg);
printf("Error %s\n", errmsg);
return;
case XML_EVENT_START_ELEMENT:
printf("<%s>", XmlEvGetName0(evctx));
break;
case XML_EVENT_END_DOCUMENT:
printf("<%s>", XmlEvGetName0(evctx));
return;
}
}
XmlEvCleanPPCtx(xctx, evctx);
}
XmlEvDestroyPPCtx(xctx, evctx);
XmlDestroy(xctx);
例20-6 解析するサンプル文書
<!DOCTYPE doc [
<!ENTITY ent SYSTEM "file:attendees.txt">
<!ELEMENT doc ANY>
<!ELEMENT meeting (topic, date, publishAttendees)>
<!ELEMENT publishAttendees (#PCDATA)>
<!ELEMENT topic (#PCDATA)>
<!ELEMENT date (#PCDATA)>
]>
<!-- Begin Document -->
<doc>
<!-- Info about the meeting -->
<meeting>
<topic>Group meeting</topic>
<date>April 25, 2005</date>
<publishAttendees>&ent;</publishAttendees>
</meeting>
</doc>
<!-- End Document -->例20-7 サンプル文書の解析により生成されたイベント
XML_EVENT_START_DOCUMENT XML_EVENT_START_DTD XML_EVENT_PE_DECLARATION XML_EVENT_ELEMENT_DECLARATION XML_EVENT_ELEMENT_DECLARATION XML_EVENT_ELEMENT_DECLARATION XML_EVENT_ELEMENT_DECLARATION XML_EVENT_ELEMENT_DECLARATION XML_EVENT_END_DTD XML_EVENT_COMMENT XML_EVENT_START_ELEMENT XML_EVENT_SPACE XML_EVENT_COMMENT XML_EVENT_SPACE XML_EVENT_START_ELEMENT XML_EVENT_START_ELEMENT XML_EVENT_CHARACTERS XML_EVENT_END_ELEMENT XML_EVENT_START_ELEMENT XML_EVENT_CHARACTERS XML_EVENT_END_ELEMENT XML_EVENT_START_ELEMENT XML_EVENT_START_ENTITY XML_EVENT_CHARACTERS XML_EVENT_END_ENTITY XML_EVENT_END_ELEMENT XML_EVENT_END_ELEMENT XML_EVENT_SPACE XML_EVENT_END_ELEMENT XML_EVENT_COMMENT XML_EVENT_END_DOCUMENT
20.7 OCIおよびXDK for C APIの使用
この項では、Oracle Call Interface(OCI)からのXDK for C関数へのアクセスについて説明します。
トピック:
- XMLType関数の使用および説明
データベースのXMLType列のXMLにC APIを使用できます。Oracle Call Interface (OCI)プログラムでは、OCIハンドルの値を初期化することで、表に格納されたXMLデータにアクセスできます。 - Oracle XML DBに対するXMLコンテキストの初期化
XMLコンテキストは、各C DOM API関数における必須パラメータです。この不透明なコンテキストは、データ・エンコーディング、エラー・メッセージ言語などに関する情報をカプセル化します。XMLコンテキストの内容は、XDKアプリケーションとOracle XML DBアプリケーションでは異なります。 - クライアントでのXMLTypeインスタンスの作成
XmlLoadDom()の起動を使用して、クライアントに新しいXMLTypeインスタンスを構築できます。 - データベース・サーバーのXMLデータに対する操作
Oracle Database上のXMLデータは、OCI文を使用して操作できます。xmldocnodeを使用してXMLType値をバインドして定義し、OCI文を使用してデータベースからXMLデータを抽出できます。このデータをC DOM関数で直接使用するか、またはSQL文に値を直接バインドできます。 - OCIおよびXDK for C APIの使用: 例
次の例では、DOM APIを使用してXMLスキーマベース文書を構築および保存する方法とデータベース文書を変更する方法を示します。
20.7.1 XMLType関数の使用および説明
データベースのXMLType列のXMLにC APIを使用できます。Oracle Call Interface (OCI)プログラムでは、OCIハンドルの値を初期化することで、表に格納されたXMLデータにアクセスできます。
これは、次のようなハンドルに適用されます。
-
環境ハンドル
-
サービス・ハンドル
-
エラー・ハンドル
-
オプションのパラメータ
プログラムでは、これらの入力値をOCIXmlDbInitXmlCtx()関数に渡すことができます。この関数によりXMLコンテキストが戻されます。プログラムによりC APIが起動された後、OCIXmlDbFreeXmlCtx()関数によってコンテキストが解放されます。
表20-6 XMLType関数
| 関数名 | 説明 |
|---|---|
|
|
空の |
|
|
ソース・バッファからの作成 |
|
|
|
|
|
Extensible Stylesheet Language Transformation (XSLT)スタイルシートを使用した変換 |
|
|
|
|
|
スキーマベースの文書かどうかのチェック |
|
|
スキーマ情報の取得 |
|
|
文書の名前空間の取得 |
|
|
スキーマを使用した検証 |
|
|
|
|
|
DOMからの |
20.7.2 Oracle XML DBに対するXMLコンテキストの初期化
XMLコンテキストは、各C DOM API関数における必須パラメータです。この不透明なコンテキストは、データ・エンコーディング、エラー・メッセージ言語などに関する情報をカプセル化します。XMLコンテキストの内容は、XDKアプリケーションとOracle XML DBアプリケーションでは異なります。
注意:
Oracle XML DBアプリケーションでXDK用のXMLコンテキストを使用したり、XDKアプリケーションでOracle XML DB用のXMLコンテキストを使用しないでください。
Oracle XML DBでは、XMLコンテキストを初期化および解放する2つのOCI関数があり、プロトタイプは次のとおりです。
xmlctx *OCIXmlDbInitXmlCtx (OCIEnv *envhp, OCISvcCtx *svchp, OCIError *errhp,
ocixmldbparam *params, ub4 num_params);
void OCIXmlDbFreeXmlCtx (xmlctx *xctx);
関連項目:
-
関数の参考資料は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください
-
XMLに対するOCIサポートの詳細は、『Oracle Call Interfaceプログラマーズ・ガイド』を参照してください
-
DOM APIの参考情報は、『Oracle Database XML C APIリファレンス』を参照してください
20.7.3 クライアントでのXMLTypeインスタンスの作成
XmlLoadDom()の起動を使用して、クライアントに新しいXMLTypeインスタンスを構築できます。
次の基本手順に従います。
XmlCreateDocument()を起動して、空のXMLTypeインスタンスを構築できます。この関数は、他のタイプに対するOCIObjectNew()に相当します。前の起動で戻された(xmldocnode *)について操作し、バインド値として提供される必要がある場合、最後にこれを(void *)にキャストできます。
20.7.4 データベース・サーバーのXMLデータに対する操作
Oracle Database上のXMLデータは、OCI文を使用して操作できます。xmldocnodeを使用してXMLType値をバインドして定義し、OCI文を使用してデータベースからXMLデータを抽出できます。このデータをC DOM関数で直接使用するか、またはSQL文に値を直接バインドできます。
20.7.5 OCIおよびXDK for C APIの使用: 例
次の例では、DOM APIを使用してXMLスキーマベース文書を構築および保存する方法とデータベース文書を変更する方法を示します。
例20-8に、DOM APIを使用してスキーマベース文書を構築し、データベースに保存する方法を示します。ヘッダー・ファイルxml.hおよびocixmldb.hをインクルードする必要があります。
例20-9に、DOM APIを使用してデータベースから文書を取得し、変更する方法を示します。
例20-8 DOM APIを使用したスキーマベース文書の構築
#include <xml.h>
#include <ocixmldb.h>
static oratext tlpxml_test_sch[] = "<TOP xmlns='example1.xsd'\n\
xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' \n\
xsi:schemaLocation='example1.xsd example1.xsd'/>";
void example1()
{
OCIEnv *envhp;
OCIError *errhp;
OCISvcCtx *svchp;
OCIStmt *stmthp;
OCIDuration dur;
OCIType *xmltdo;
xmldocnode *doc;
ocixmldbparam params[1];
xmlnode *quux, *foo, *foo_data;
xmlerr err;
/* Initialize envhp, svchp, errhp, dur, stmthp */
/* ........ */
/* Get an xml context */
params[0].name_ocixmldbparam = XCTXINIT_OCIDUR;
params[0].value_ocixmldbparam = &dur;
xctx = OCIXmlDbInitXmlCtx(envhp, svchp, errhp, params, 1);
/* Start processing */
printf("Supports XML 1.0: %s\n",
XmlHasFeature(xctx, (oratext *) "xml", (oratext *) "1.0") ? "YES" : "NO");
/* Parsing a schema-based document */
if (!(doc = XmlLoadDom(xctx, &err, "buffer", tlpxml_test_sch,
"buffer_length", sizeof(tlpxml_test_sch)-1,
"validate", TRUE, NULL)))
{
printf("Parse failed, code %d\n");
return;
}
/* Create some elements and add them to the document */
top = XmlDomGetDocElem(xctx, doc);
quux = (xmlnode *) XmlDomCreateElem(xctx ,doc, (oratext *) "QUUX");
foo = (xmlnode *) XmlDomCreateElem(xctx, doc, (oratext *) "FOO");
foo_data = (xmlnode *) XmlDomCreateText(xctx, doc, (oratext *)"foo's data");
foo_data = XmlDomAppendChild(xctx, (xmlnode *) foo, (xmlnode *) foo_data);
foo = XmlDomAppendChild(xctx, quux, foo);
quux = XmlDomAppendChild(xctx, top, quux);
XmlSaveDom(xctx, &err, top, "stdio", stdout, NULL);
XmlSaveDom(xctx, &err, doc, "stdio", stdout, NULL);
/* Insert the document to my_table */
ins_stmt = "insert into my_table values (:1)";
status = OCITypeByName(envhp, errhp, svchp, (const text *) "SYS",
(ub4) strlen((char *)"SYS"), (const text *) "XMLTYPE",
(ub4) strlen((char *)"XMLTYPE"), (CONST text *) 0,
(ub4) 0, dur, OCI_TYPEGET_HEADER,
(OCIType **) &xmltdo)) ;
if (status == OCI_SUCCESS)
{
exec_bind_xml(svchp, errhp, stmthp, (void *)doc, xmltdo, ins_stmt));
}
/* free xml ctx */
OCIXmlDbFreeXmlCtx(xctx);
}
/*--------------------------------------------------------*/
/* execute a sql statement which binds xml data */
/*--------------------------------------------------------*/
sword exec_bind_xml(svchp, errhp, stmthp, xml, xmltdo, sqlstmt)
OCISvcCtx *svchp;
OCIError *errhp;
OCIStmt *stmthp;
void *xml;
OCIType *xmltdo;
OraText *sqlstmt;
{
OCIBind *bndhp1 = (OCIBind *) 0;
OCIBind *bndhp2 = (OCIBind *) 0;
sword status = 0;
OCIInd ind = OCI_IND_NOTNULL;
OCIInd *indp = &ind;
if(status = OCIStmtPrepare(stmthp, errhp, (OraText *)sqlstmt,
(ub4)strlen((char *)sqlstmt),
(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)) {
return OCI_ERROR;
}
if(status = OCIBindByPos(stmthp, &bndhp1, errhp, (ub4) 1, (dvoid *) 0,
(sb4) 0, SQLT_NTY, (dvoid *) 0, (ub2 *)0,
(ub2 *)0, (ub4) 0, (ub4 *) 0, (ub4) OCI_DEFAULT)) {
return OCI_ERROR;
}
if(status = OCIBindObject(bndhp1, errhp, (CONST OCIType *) xmltdo,
(dvoid **) &xml, (ub4 *) 0, (dvoid **) &indp, (ub4 *) 0)) {
return OCI_ERROR;
}
if(status = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
(CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)) {
return OCI_ERROR;
}
return OCI_SUCCESS;
}
例20-9 DOM APIを使用したデータベース文書の変更
#include <xml.h>
#include <ocixmldb.h>
sword example2()
{
OCIEnv *envhp;
OCIError *errhp;
OCISvcCtx *svchp;
OCIStmt *stmthp;
OCIDuration dur;
OCIType *xmltdo;
xmldocnode *doc;
xmlnodelist *item_list; ub4 ilist_l;
ocixmldbparam params[1];
text *sel_xml_stmt = (text *)"SELECT xml_col FROM my_table";
ub4 xmlsize = 0;
sword status = 0;
OCIDefine *defnp = (OCIDefine *) 0;
/* Initialize envhp, svchp, errhp, dur, stmthp */
/* ... */
/* Get an xml context */
params[0].name_ocixmldbparam = XCTXINIT_OCIDUR;
params[0].value_ocixmldbparam = &dur;
xctx = OCIXmlDbInitXmlCtx(envhp, svchp, errhp, params, 1);
/* Start processing */
if(status = OCITypeByName(envhp, errhp, svchp, (const text *) "SYS",
(ub4) strlen((char *)"SYS"), (const text *) "XMLTYPE",
(ub4) strlen((char *)"XMLTYPE"), (CONST text *) 0,
(ub4) 0, dur, OCI_TYPEGET_HEADER,
(OCIType **) xmltdo_p)) {
return OCI_ERROR;
}
if(!(*xmltdo_p)) {
printf("NULL tdo returned\n");
return OCI_ERROR;
}
if(status = OCIStmtPrepare(stmthp, errhp, (OraText *)selstmt,
(ub4)strlen((char *)selstmt),
(ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT)) {
return OCI_ERROR;
}
if(status = OCIDefineByPos(stmthp, &defnp, errhp, (ub4) 1, (dvoid *) 0,
(sb4) 0, SQLT_NTY, (dvoid *) 0, (ub2 *)0,
(ub2 *)0, (ub4) OCI_DEFAULT)) {
return OCI_ERROR;
}
if(status = OCIDefineObject(defnp, errhp, (OCIType *) *xmltdo_p,
(dvoid **) &doc,
&xmlsize, (dvoid **) 0, (ub4 *) 0)) {
return OCI_ERROR;
}
if(status = OCIStmtExecute(svchp, stmthp, errhp, (ub4) 1, (ub4) 0,
(CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT)) {
return OCI_ERROR;
}
/* We have the doc. Now we can operate on it */
printf("Getting Item list...\n");
item_list = XmlDomGetElemsByTag(xctx,(xmlelemnode *) elem,(oratext *)"Item");
ilist_l = XmlDomGetNodeListLength(xctx, item_list);
printf(" Item list length = %d \n", ilist_l);
for (i = 0; i < ilist_l; i++)
{
elem = XmlDomGetNodeListItem(xctx, item_list, i);
printf("Elem Name:%s\n", XmlDomGetNodeName(xctx, fragelem));
XmlDomRemoveChild(xctx, fragelem);
}
XmlSaveDom(xctx, &err, doc, "stdio", stdout, NULL);
/* free xml ctx */
OCIXmlDbFreeXmlCtx(xctx);
return OCI_SUCCESS;
}