14 C DOM API for XMLType
C DOM API for XMLType
では、CでDOMを使用してXMLType
インスタンスを操作できます。
- C DOM API for XMLTypeの概要
C DOM API forXMLType
は、Oracle XML Developer's Kit (XDK)およびOracle XML DBで使用されるDOM APIです。データベース内外のXMLデータに対してこれを使用できます。 - OCIを使用したデータベースに格納されているXMLTypeデータへのアクセス
Oracle XML DBでは、抽象データ型XMLType
を使用したXMLインスタンスの格納および操作がサポートされています。これらのXMLインスタンスは、C DOM API for XMLとともにOracle Call Interface(OCI)を使用して、クライアント側でアクセスおよび操作できます。 - クライアントでのXMLTypeインスタンスの作成
C DOM APIメソッドのXMLCreateDocument()
およびXmlLoadDom()
を使用して、クライアント側に新しいXMLType
インスタンスを構成できます。 - C DOM API関数のXMLコンテキスト・パラメータ
XMLコンテキストは、すべてのC DOM API関数に必須のパラメータです。このOPAQUE型のコンテキストは、データ・エンコーディング、エラー・メッセージの言語などに関係する情報をカプセル化します。コンテキストの内容は、Oracle XML Developer's KitアプリケーションおよびOracle XML DBに対して異なります。 - XMLコンテキストの初期化および終了
C DOM APIを使用してXML文書を構成し、Oracle Databaseにこれを保存するCプログラムの例を示します。 - バイナリXMLでのC API for XMLの使用
C APIを使用して、Oracle XML DBに対して、バイナリXML形式でエンコードされたXMLデータを読み書きできます。この処理には通常の読書きプロシージャが関与します。 - Oracle XML DBでのOracle XML Developer's Kit Pull Parserの使用
Oracle XML DBで、XMLType
インスタンスによりOracle XML Developer's Kit Pull Parserを使用できます。このパーサーを使用する場合、解析はオン・デマンドで行われ、アプリケーションが解析処理を起動します。 - Cでの一般的なXMLType操作
一般的なXML操作は、C API for XMLによって提供されます。
親トピック: XMLType API
14.1 C DOM API for XMLTypeの概要
C DOM API for XMLType
は、Oracle XML Developer's Kit (XDK)およびOracle XML DBで使用されるDOM APIです。データベース内外のXMLデータに対してこれを使用できます。
DOMは、World Wide Web Consortium (W3C)のDOM 2.0勧告に準拠していることを示しています。
C DOM API for XMLType
には、XDKでXMLデータの従来の記憶域に、またはOracle XML DBで表のXMLType
列として記憶域に使用できるパフォーマンス向上拡張機能もあります。
注意:
Oracle Database 10gリリース1以前のリリースのC DOM関数は、下位互換性のみの目的でサポートされています。
C DOM API for XMLType
は、Oracle XML DBのXMLType
上に実装されます。W3CのDOM勧告において、ドキュメントという用語は広い意味(URI、ファイル・システム、メモリー・バッファ、標準入出力)で使用されます。C DOM API for XMLType
は、Oracle XML Developer's KitおよびOracle XML DBアプリケーションに必要なすべての機能を含んだ結合プログラム・インタフェースです。これは、XSLTおよびXML Schemaの実装用に提供されています。DOM 2.0勧告に厳密に従っていましたが、オブジェクト指向のDOM 2.0勧告からフラットCの名前空間へのマッピングにはいくつかのネーミング変更が必要でした。たとえば、getName()
()メソッドは、getAttrName()
メソッドに名前が変更されました
C DOM API for XMLType
は以前のOracle APIに置き換わります。特に、oraxml
インタフェース(最上位、DOM、SAXおよびXSLT)およびoraxsd.h
(Schema)インタフェースは、将来のリリースで非推奨になる予定です。
XMLデータの操作に使用できるCおよびC++のApplication Program Interface (API)のリファレンス・ドキュメントは、Oracle Database XML C APIリファレンスおよびOracle Database XML C++ APIリファレンスです。
関連項目:
-
PL/SQL API for XMLの詳細は、『Oracle Database PL/SQLパッケージおよびタイプ・リファレンス』を参照してください。
-
Java API for XMLの詳細は、Oracle Database XML Java APIリファレンスを参照してください。
親トピック: C DOM API for XMLType
14.2 OCIを使用したデータベースに格納されているXMLTypeデータへのアクセス
Oracle XML DBでは、抽象データ型XMLType
を使用したXMLインスタンスの格納および操作がサポートされています。これらのXMLインスタンスは、C DOM API for XMLとともにOracle Call Interface(OCI)を使用して、クライアント側でアクセスおよび操作できます。
C DOM構造xmldocnode
を使用してXMLType
をバインドおよび定義できます。この構造は、OCI文でXML値のバインド、定義および操作に使用できます。OCI文を使用してサーバーからXMLデータを選択し、C DOM API関数で使用できます。同様に、値はSQL文に直接バインドしなおすことができます。
アプリケーション・プログラムのメイン・フローには、サーバー・ハンドルや文ハンドルなど、通常のOCIハンドルの初期化の後に、XMLコンテキスト・パラメータの初期化が続きます。その後で、データベースでXMLインスタンスを操作するか、またはクライアント側で新規インスタンスを作成できます。初期化されたXMLコンテキストは、すべてのC DOM関数で使用できます。
関連トピック
親トピック: C DOM API for XMLType
14.3 クライアントでのXMLTypeインスタンスの作成
C DOM APIメソッドのXMLCreateDocument()
およびXmlLoadDom()
を使用して、クライアント側に新しいXMLType
インスタンスを構成できます。
XMLCreateDocument()
を使用して、空のXMLType
インスタンスを構成できます。これは、他の型に対してOCIObjectNew()
を使用するのに類似しています。
次のように、XmlLoadDom()
を使用して、空でないXMLType
インスタンスを構成します。
例14-1
に示すように、xmlctxを初期化します。- ユーザー・バッファ、ローカル・ファイルまたはURIからXMLデータを構成します。これらの戻り値は(
xmldocnode *
)で、他の一般的なC APIで使用できます。 - 必要に応じて、(
xmldocnode *
)を(void*
)にキャストし、バインド値として直接提供できます。
親トピック: C DOM API for XMLType
14.4 C DOM API関数のXMLコンテキスト・パラメータ
XMLコンテキストは、すべてのC DOM API関数に必須のパラメータです。このOPAQUE型のコンテキストは、データ・エンコーディング、エラー・メッセージの言語などに関係する情報をカプセル化します。コンテキストの内容は、Oracle XML Developer's KitアプリケーションおよびOracle XML DBに対して異なります。
Oracle XML DBでは、OCI関数OCIXmlDbInitXmlCtx()
でXMLコンテキストを初期化し、OCIXmlDbFreeXmlCtx()
でXMLコンテキストを終了します。
- OCIXmlDbInitXmlCtx()の構文
OCI関数OCIXmlDbInitXmlCtx()
は、XMLコンテキストを初期化します。 - OCIXmlDbFreeXmlCtx()の構文
OCI関数OCIXmlDbFreeXmlCtx()
は、XMLコンテキストを終了します。
親トピック: C DOM API for XMLType
14.4.1 OCIXmlDbInitXmlCtx()の構文
OCI関数OCIXmlDbInitXmlCtx()
は、XMLコンテキストを初期化します。
OCIXmlDbInitXmlCtx()
の構文は次のとおりです。
xmlctx *OCIXmlDbInitXMlCtx (OCIEnv *envhp,
OCISvcHp *svchp,
OCIError *errhp,
ocixmldbparam *params,
ub4 num_params);
表14-1に、パラメータを示します。
表14-1 OCIXmlDbInitXMlCtx()のパラメータ
パラメータ | 説明 |
---|---|
|
OCI環境ハンドルです。 |
|
OCIサービス・ハンドルです。 |
|
OCIエラー・ハンドルです。 |
|
オプション値の配列:
|
|
|
親トピック: C DOM API関数のXMLコンテキスト・パラメータ
14.4.2 OCIXmlDbFreeXmlCtx()の構文
OCI関数OCIXmlDbFreeXmlCtx()
は、XMLコンテキストを終了します。
xctx (IN)
パラメータが終了対象のXMLコンテキストである場合のOCIXmlDbFreeXmlCtx()
の構文は次のとおりです。
void OCIXmlDbFreeXmlCtx (xmlctx *xctx);
親トピック: C DOM API関数のXMLコンテキスト・パラメータ
14.5 XMLコンテキストの初期化および終了
C DOM APIを使用してXML文書を構成し、Oracle Databaseにこれを保存するCプログラムの例を示します。
例14-1に、これを示します。構成された文書は、表my_table
に格納されます。OCI関数のOCIXmlDbInitXmlCtx()
およびOCIXmlDbFreeXmlCtx()
は、それぞれXMLコンテキストを初期化および終了するために使用されます。これらの関数は、ヘッダー・ファイルocixmldb.h
で定義されます。
コードでは、ここには示されていない、ヘルパー関数のexec_bind_xml
、init_oci_handles
およびfree_oci_handles
が使用されます。ヘルパー関数を含む、この例の完全なリストは、Oracleが提供するXML Schemaおよび例のXMLコンテキスト(OCI)の初期化および終了を参照してください。
例14-1のCコードでは、データベース・スキーマcapiuser
でmy_table
表を作成するため、次のSQLコードを最初に実行したことを前提としています。
CONNECT CAPIUSER
Enter password: password
Connected.
CREATE TABLE my_table OF XMLType;
例14-1 OCIXMLDBINITXMLCTX()およびOCIXMLDBFREEXMLCTX()の使用
#ifndef S_ORACLE
#endif
#ifndef ORATYPES_ORACLE
#include <oratypes.h>
#endif
#ifndef XML_ORACLE
#include <xml.h>
#endif
#ifndef OCIXML_ORACLE
#include <ocixml.h>
#endif
#ifndef OCI_ORACLE
#include <oci.h>
#endif
#include <string.h>
typedef struct test_ctx {
OCIEnv *envhp;
OCIError *errhp;
OCISvcCtx *svchp;
OCIStmt *stmthp;
OCIServer *srvhp;
OCIDuration dur;
OCISession *sesshp;
oratext *username;
oratext *password;
} test_ctx;
/* Helper function 1: execute a sql statement which binds xml data */
static sword exec_bind_xml(OCISvcCtx *svchp,
OCIError *errhp,
OCIStmt *stmthp,
void *xml,
OCIType *xmltdo,
OraText *sqlstmt);
/* Helper function 2: Initialize OCI handles and connect */
static sword init_oci_handles(test_ctx *ctx);
/* Helper function 3: Free OCI handles and disconnect */
static sword free_oci_handles(test_ctx *ctx);
void main()
{
test_ctx temp_ctx;
test_ctx *ctx = &temp_ctx;
OCIType *xmltdo = (OCIType *) 0;
xmldocnode *doc = (xmldocnode *)0;
ocixmldbparam params[1];
xmlnode *quux, *foo, *foo_data, *top;
xmlerr err;
sword status = 0;
xmlctx *xctx;
oratext ins_stmt[] = "insert into my_table values (:1)";
oratext tlpxml_test_sch[] = "<TOP/>";
ctx->username = (oratext *)"capiuser";
ctx->password = (oratext *)"***********"; /* Replace with real password */
/* Initialize envhp, svchp, errhp, dur, stmthp */
init_oci_handles(ctx);
/* Get an xml context */
params[0].name_ocixmldbparam = XCTXINIT_OCIDUR;
params[0].value_ocixmldbparam = &ctx->dur;
xctx = OCIXmlDbInitXmlCtx(ctx->envhp, ctx->svchp, ctx->errhp, params, 1);
/* Start processing - first, check that this DOM supports XML 1.0 */
printf("\n\nSupports XML 1.0? : %s\n",
XmlHasFeature(xctx, (oratext *) "xml", (oratext *) "1.0") ?
"YES" : "NO");
/* Parse a 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", err);
}
else
{
/* Get the document element */
top = (xmlnode *)XmlDomGetDocElem(xctx, doc);
/* Print out the top element */
printf("\n\nOriginal top element is :\n");
XmlSaveDom(xctx, &err, top, "stdio", stdout, NULL);
/* Print out the document. The changes are reflected here */
printf("\n\nOriginal document is :\n");
XmlSaveDom(xctx, &err, (xmlnode *)doc, "stdio", stdout, NULL);
/* Create some elements and add them to the document */
quux = (xmlnode *) XmlDomCreateElem(xctx ,doc, (oratext *) "QUUX");
foo = (xmlnode *) XmlDomCreateElem(xctx, doc, (oratext *) "FOO");
foo_data = (xmlnode *) XmlDomCreateText(xctx, doc, (oratext *) "data");
foo_data = XmlDomAppendChild(xctx, (xmlnode *) foo, (xmlnode *) foo_data);
foo = XmlDomAppendChild(xctx, quux, foo);
quux = XmlDomAppendChild(xctx, top, quux);
/* Print out the top element */
printf("\n\nNow the top element is :\n");
XmlSaveDom(xctx, &err, top, "stdio", stdout, NULL);
/* Print out the document. The changes are reflected here */
printf("\n\nNow the document is :\n");
XmlSaveDom(xctx, &err, (xmlnode *)doc, "stdio", stdout, NULL);
/* Insert the document into my_table */
status = OCITypeByName(ctx->envhp, ctx->errhp, ctx->svchp,
(const text *) "SYS", (ub4) strlen((char *)"SYS"),
(const text *) "XMLTYPE",
(ub4) strlen((char *)"XMLTYPE"), (CONST text *) 0,
(ub4) 0, OCI_DURATION_SESSION, OCI_TYPEGET_HEADER,
(OCIType **) &xmltdo);
if (status == OCI_SUCCESS)
{
exec_bind_xml(ctx->svchp, ctx->errhp, ctx->stmthp, (void *)doc, xmltdo,
ins_stmt);
}
}
/* Free xml ctx */
OCIXmlDbFreeXmlCtx(xctx);
/* Free envhp, svchp, errhp, stmthp */
free_oci_handles(ctx);
}
このCプログラムのコンパイルおよび実行からの出力は、次のとおりです。
Supports XML 1.0? : YES Original top element is : <TOP/> Original document is : <TOP/> Now the top element is : <TOP> <QUUX> <FOO>data</FOO> </QUUX> </TOP> Now the document is : <TOP> <QUUX> <FOO>data</FOO> </QUUX> </TOP>
これは、my_table
で構成された文書を問い合せた結果です。
SELECT * FROM my_table; SYS_NC_ROWINFO$ --------------- <TOP> <QUUX> <FOO>data</FOO> </QUUX> </TOP> 1 row selected.
親トピック: C DOM API for XMLType
14.6 バイナリXMLでのC API for XMLの使用
C APIを使用して、Oracle XML DBに対して、バイナリXML形式でエンコードされたXMLデータを読み書きすることができます。この処理には通常の読書きプロシージャが関与します。
バイナリXMLはXMLデータの簡潔な、XML Schema対応のエンコーディングです。バイナリXMLはデータベース内のXMLType
データの記憶域モデルとして使用できますが、データベース外にあるXMLデータにも使用することができます。
バイナリXMLデータはXML Schemaに対応しており、必要に応じて、各種のコード体系を使用できます。バイナリXMLデータを操作するには、関連するXML Schemaとエンコーディングについて、データとこのメタデータの両方が必要です。
データベースに格納されているXMLType
データの場合、このメタデータもデータベースに格納されます。ただし、データベースとデータのセットアップに応じて、メタデータが適用されるデータと同一のサーバーにメタデータが格納されない場合があります。この場合、データベースに対してバイナリXMLデータを読書きするためには、次のステップを実行する必要があります。
-
メタデータのコンテキスト・インスタンスを作成します。
-
このコンテキストを、データベース内のバイナリXMLデータにアクセスするために使用するデータ接続に関連付けます。データ接続は、専用接続(
OCISvcCtx
)でも接続プール(OCICPool
)でもかまいません。
すると、アプリケーションがデータ接続上でバイナリXMLデータをエンコードまたはデコードする必要がある場合、それに必要なメタデータが自動的にフェッチされます。例14-2に示すように、一連の動作の全体は次のとおりです。
-
環境(
OCIEnv
)、接続(OCISvcCtx
)、エラー・コンテキスト(OCIError
)に応じて、通常のOCIハンドルを作成します。 -
必要に応じて1つ以上のメタデータ・コンテキストを作成します。メタデータ・コンテキストはメタデータ・リポジトリと呼ばれることもあり、
OCIBinXMLReposCtx
はOCIコンテキスト・データ構造です。専用接続からはOCIBinXMLCreateReposCtxFromConn
を使用して、接続プールからはOCIBinXMLCreateReposCtxFromCPool
を使用してメタデータ・コンテキストを作成します。 -
メタデータ・コンテキストをバイナリXMLデータ接続に関連付けます。これには
OCIBinXmlSetReposCtxForConn
を使用します。 -
(オプション)XMLデータがデータベース外に由来するものの場合は、
setPicklePreference
を使用して、それ以降データベースに送信されるXMLデータがバイナリXML形式になるよう指定します。これは、DOM文書(xmldomdoc
)に適用されます。バイナリXMLを指定しない場合、データはテキスト(CLOB
)として格納されます。 -
OCIライブラリを使用して、データベースに対してXMLデータを読書きします。バイナリXML文書のエンコードやデコードに必要なときは常に、メタデータ・コンテキストを使用して、必要なメタデータが自動的にフェッチされます。C DOM API for XMLを使用して、クライアント・レベルのXMLデータに対して操作します。
例14-2 バイナリXMLでのC API for XMLの使用
. . . /* Private types and constants */ #define SCHEMA (OraText *)"SYS" #define TYPE (OraText *)"XMLTYPE" #define USER (OraText *)"oe" #define USER_LEN (ub2)(strlen((char *)USER)) #define PWD (OraText *)"oe" #define PWD_LEN (ub2)(strlen((char *)PWD)) #define NUM_PARAMS 1 static void checkerr(OCIError *errhp, sword status); static sword create_env(OraText *user, ub2 user_len, OraText *pwd, ub2 pwd_len, OCIEnv **envhp, OCISvcCtx **svchp, OCIError **errhp); static sword run_example(OCIEnv *envhp, OCISvcCtx *svchp, OCIError *errhp, OCIDuration dur); static void cleanup(OCIEnv *envhp, OCISvcCtx *svchp, OCIError *errhp); int main (int argc, char *argv[]) { OCIEnv *envhp; OCISvcCtx *svchp; OCIError *errhp; printf("*** Starting Binary XML Example program\n"); if (create_env(USER, USER_LEN, PWD, PWD_LEN, &envhp, &svchp, &errhp)) { printf("FAILED: create_env()\n"); cleanup(envhp, svchp, errhp); return OCI_ERROR; } if (run_example(envhp, svchp, errhp, OCI_DURATION_SESSION)) { printf("FAILED: run_example()\n"); cleanup(envhp, svchp, errhp); return OCI_ERROR; } cleanup(envhp, svchp, errhp); printf ("*** Completed Binary XML example\n"); return OCI_SUCCESS; } static sword create_env(OraText *user, ub2 user_len, OraText *pwd, ub2 pwd_len, OCIEnv **envhp, OCISvcCtx **svchp, OCIError **errhp) { sword status; OCIServer *srvhp; OCISession *usrp; OCICPool *poolhp; OraText *poolname; ub4 poolnamelen; OraText *database =(OraText *)""; OCIBinXmlReposCtx *rctx; /* Create and initialize environment. Allocate error handle. */ . . . if ((status = OCIConnectionPoolCreate((dvoid *)*envhp, (dvoid*)*errhp, (dvoid *)poolhp, &poolname, (sb4 *)&poolnamelen, (OraText *)0, (sb4) 0, 1, 10, 1, (OraText *)USER, (sb4) USER_LEN, (OraText *)PWD, (sb4) PWD_LEN, OCI_DEFAULT)) != OCI_SUCCESS) { printf ("OCIConnectionPoolCreate - Fail %d\n", status); return OCI_ERROR; } status = OCILogon2((OCIEnv *)*envhp, *errhp, svchp, (OraText *)USER, (ub4)USER_LEN, (const oratext *)PWD, (ub4)PWD_LEN, (const oratext *)poolname, poolnamelen, OCI_CPOOL); if (status) { printf ("OCILogon2 - Fail %d\n", status); return OCI_ERROR; } OCIBinXmlCreateReposCtxFromCPool(*envhp, poolhp, *errhp, &rctx); OCIBinXmlSetReposCtxForConn(*svchp, rctx); return OCI_SUCCESS; } static sword run_example(OCIEnv *envhp, OCISvcCtx *svchp, OCIError *errhp, OCIDuration dur) { OCIType *xmltdo = (OCIType *)0; OCIStmt *stmthp; OCIDefine *defnp; xmldocnode *xmldoc = (xmldocnode *)0; ub4 xmlsize = 0; text *selstmt = (text *)"SELECT doc FROM po_binxmltab"; sword status; struct xmlctx *xctx = (xmlctx *) 0; ocixmldbparam params[NUM_PARAMS]; xmlerr xerr = (xmlerr) 0; /* Obtain type definition for XMLType. Allocate statement handle. Prepare SELECT statement. Define variable for XMLType. Execute statement. */ . . . /* Construct xmlctx for using XML C API */ params[0].name_ocixmldbparam = XCTXINIT_OCIDUR; params[0].value_ocixmldbparam = &dur; xctx = OCIXmlDbInitXmlCtx(envhp, svchp, errhp, params, NUM_PARAMS); /* Print result to local string */ XmlSaveDom(xctx, &xerr, (xmlnode *)xmldoc, "stdio", stdout, NULL); /* Free instances */ . . . }
関連トピック
親トピック: C DOM API for XMLType
14.7 Oracle XML DBでのOracle XML Developer's Kit Pull Parserの使用
Oracle XML DBで、XMLType
インスタンスによりOracle XML Developer's Kit Pull Parserを使用できます。このパーサーを使用する場合、解析はオン・デマンドで行われ、アプリケーションが解析処理を起動します。
アプリケーションは、Simple API for XML(SAX)解析同様、開始タグ、終了タグ、およびコメントにより一連のイベントを介してXML文書にアクセスします。ただし、解析イベントがコールバックで処理されるSAX解析とは異なり、プル解析では、必要な場合のみ(pull)イベントを要求するメソッドがコールされます。これにより、アプリケーションはXML処理の制御をより容易にできます。特に、PullパーサーではSAXパーサーよりフィルタリングに柔軟性があります。
Oracle XML Developer's Kit Pull Parserを使用して、ストリームに基づくXML Schemaの検証もできます。
例14-3は、XMLType
インスタンスによるOracle XML DB Pull Parserの使用方法を示しています。Pullパーサーを使用するには、UNIXシステムおよびLinuxシステムではlibxml10.a
静的ライブラリ、Microsoft Windowsシステムではoraxml10.dll
が必要です。また、xmlev.h
ヘッダー・ファイルも必要です。
関連項目:
-
Oracle XML Developer's Kit Pull Parserの詳細は、Oracle XML Developer's Kitプログラマーズ・ガイドを参照してください。
-
ストリームに基づく検証のPullパーサーの使用方法の詳細は、Oracle XML Developer's Kitプログラマーズ・ガイドを参照してください。
例14-3 Oracle XML DB Pull Parserの使用
#define MAXBUFLEN 64*1024 void main() { test_ctx temp_ctx; test_ctx *ctx = &temp_ctx; OCIType *xmltdo = (OCIType *) 0; ocixmldbparam params[1]; sword status = 0; xmlctx *xctx; OCIDefine *defnp = (OCIDefine *) 0; oratext sel_stmt[] = "SELECT XMLSerialize(DOCUMENT x.OBJECT_VALUE AS CLOB) FROM PURCHASEORDER x where rownum = 1"; OCILobLocator *cob; ub4 amtp, nbytes; ub1 bufp[MAXBUFLEN]; ctx->username = (oratext *)"oe"; ctx->password = (oratext *)"*************"; /* Replace with real password */ /* Initialize envhp, svchp, errhp, dur, stmthp */ init_oci_handles(ctx); /* Get an xml context */ params[0].name_ocixmldbparam = XCTXINIT_OCIDUR; params[0].value_ocixmldbparam = &ctx->dur; xctx = OCIXmlDbInitXmlCtx(ctx->envhp, ctx->svchp, ctx->errhp, params, 1); /* Start processing */ printf("\n\nSupports XML 1.0? : %s\n", XmlHasFeature(xctx, (oratext *) "xml", (oratext *) "1.0") ? "YES" : "NO"); /* Allocate the lob descriptor */ status = OCIDescriptorAlloc((dvoid *) ctx->envhp, (dvoid **) &clob, (ub4)OCI_DTYPE_LOB, (size_t) 0, (dvoid **) 0); if (status) { printf("OCIDescriptorAlloc Failed\n"); goto error; } status = OCIStmtPrepare(ctx->stmthp, ctx->errhp, (CONST OraText *)sel_stmt, (ub4) strlen((char *)sel_stmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); if (status) { printf("OCIStmtPrepare Failed\n"); goto error; } status = OCIDefineByPos(ctx->stmthp, &defnp, ctx->errhp, (ub4) 1, (dvoid *) &clob, (sb4) -1, (ub2 ) SQLT_CLOB, (dvoid *) 0, (ub2 *)0, (ub2 *)0, (ub4) OCI_DEFAULT); if (status) { printf("OCIDefineByPos Failed\n"); goto error; } status = OCIStmtExecute(ctx->svchp, ctx->stmthp, ctx->errhp, (ub4) 1, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT); if (status) { printf("OCIStmtExecute Failed\n"); goto error; } /* read the fetched value into a buffer */ amtp = nbytes = MAXBUFLEN-1; status = OCILobRead(ctx->svchp, ctx->errhp, clob, &amtp, (ub4) 1, (dvoid *) bufp, (ub4) nbytes, (dvoid *)0, (sb4 (*)(dvoid *, CONST dvoid *, ub4, ub1)) 0, (ub2) 0, (ub1) SQLCS_IMPLICIT); if (status) { printf("OCILobRead Failed\n"); goto error; } bufp[amtp] = '\0'; if (amtp > 0) { printf("\n=> Query result of %s: \n%s\n", sel_stmt, bufp); /********** PULL PARSING ******************/ status = pp_parse(xctx, bufp, amtp); if (status) printf("Pull Parsing failed\n"); } error: /* Free XML Ctx */ OCIXmlDbFreeXmlCtx(xctx); /* Free envhp, svchp, errhp, stmthp */ free_oci_handles(ctx); } #define ERRBUFLEN 256 sb4 pp_parse(xctx, buf, amt) xmlctx *xctx; oratext *buf; ub4 amt; { xmlevctx *evctx; xmlerr xerr = XMLERR_OK; oratext message[ERRBUFLEN]; oratext *emsg = message; xmlerr ecode; boolean done, inattr = FALSE; xmlevtype event; /* Create an XML event context - Pull Parser Context */ evctx = XmlEvCreatePPCtx(xctx, &xerr, "expand_entities", FALSE, "validate", TRUE, "attr_events", TRUE, "raw_buffer_len", 1024, NULL); if (!evctx) { printf("FAILED: XmlEvCreatePPCtx: %d\n", xerr); return OCI_ERROR; } /* Load the document from input buffer */ xerr = XmlEvLoadPPDoc(xctx, evctx, "buffer", buf, amt, "utf-8"); if (xerr) { printf("FAILED: XmlEvLoadPPDoc: %d\n", xerr); return OCI_ERROR; } /* Process the events until END_DOCUMENT event or error */ done = FALSE; while(!done) { event = XmlEvNext(evctx); switch(event) { case XML_EVENT_START_ELEMENT: printf("START ELEMENT: %s\n", XmlEvGetName0(evctx)); break; case XML_EVENT_END_ELEMENT: printf("END ELEMENT: %s\n", XmlEvGetName0(evctx)); break; case XML_EVENT_START_DOCUMENT: printf("START DOCUMENT\n"); break; case XML_EVENT_END_DOCUMENT: printf("END DOCUMENT\n"); done = TRUE; break; case XML_EVENT_START_ATTR: printf("START ATTRIBUTE: %s\n", XmlEvGetAttrName0(evctx, 0)); inattr = TRUE; break; case XML_EVENT_END_ATTR: printf("END ATTRIBUTE: %s\n", XmlEvGetAttrName0(evctx, 0)); inattr = FALSE; break; case XML_EVENT_CHARACTERS: if (inattr) printf("ATTR VALUE: %s\n", XmlEvGetText0(evctx)); else printf("TEXT: %s\n", XmlEvGetText0(evctx)); break; case XML_EVENT_ERROR: case XML_EVENT_FATAL_ERROR: done = TRUE; ecode = XmlEvGetError(evctx, &emsg); printf("ERROR: %d: %s\n", ecode, emsg); break; } } /* Destroy the event context */ XmlEvDestroyPPCtx(xctx, evctx); return OCI_SUCCESS; }
このCプログラムのコンパイルおよび実行からの出力は、次のとおりです。
=> Query result of XMLSerialize(DOCUMENT x.OBJECT_VALUE AS CLOB) FROM PURCHASEORDER x where rownum = 1:
<PurchaseOrder xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation= "http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd"> <Reference>AMCEWEN-20021009123336171PDT</Reference> <Actions> <Action> <User>KPARTNER</User> </Action> </Actions> <Reject/> <Requestor>Allan D. McEwen</Requestor> <User>AMCEWEN</User> <CostCenter>S30</CostCenter> <ShippingInstructions> <name>Allan D. McEwen</name> <address>Oracle Plaza Twin Dolphin Drive Redwood Shores CA 94065 USA</address> <telephone>650 506 7700</telephone> </ShippingInstructions> <SpecialInstructions>Ground</SpecialInstructions> <LineItems> <LineItem ItemNumber="1"> <Description>Salesman</Description> <Part Id="37429158920" UnitPrice="39.95" Quantity="2"/> </LineItem> . . . </LineItems> </PurchaseOrder> START DOCUMENT START ELEMENT: PurchaseOrder START ATTRIBUTE: xmlns:xsi ATTR VALUE: http://www.w3.org/2001/XMLSchema-instance END ATTRIBUTE: xmlns:xsi START ATTRIBUTE: xsi:noNamespaceSchemaLocation ATTR VALUE: http://localhost:8080/source/schemas/poSource/xsd/purchaseOrder.xsd END ATTRIBUTE: xsi:noNamespaceSchemaLocation START ELEMENT: Reference TEXT: AMCEWEN-20021009123336171PDT END ELEMENT: Reference START ELEMENT: Actions START ELEMENT: Action START ELEMENT: User TEXT: KPARTNER END ELEMENT: User END ELEMENT: Action END ELEMENT: Actions START ELEMENT: Reject END ELEMENT: Reject START ELEMENT: Requestor TEXT: Allan D. McEwen END ELEMENT: Requestor START ELEMENT: User TEXT: AMCEWEN END ELEMENT: User START ELEMENT: CostCenter TEXT: S30 END ELEMENT: CostCenter START ELEMENT: ShippingInstructions START ELEMENT: name TEXT: Allan D. McEwen END ELEMENT: name START ELEMENT: address TEXT: Oracle Plaza Twin Dolphin Drive Redwood Shores CA 94065 USA END ELEMENT: address START ELEMENT: telephone TEXT: 650 506 7700 END ELEMENT: telephone END ELEMENT: ShippingInstructions START ELEMENT: SpecialInstructions TEXT: Ground END ELEMENT: SpecialInstructions START ELEMENT: LineItems START ELEMENT: LineItem START ATTRIBUTE: ItemNumber ATTR VALUE: 1 END ATTRIBUTE: ItemNumber START ELEMENT: Description TEXT: Salesman END ELEMENT: Description START ELEMENT: Part START ATTRIBUTE: Id ATTR VALUE: 37429158920 END ATTRIBUTE: Id START ATTRIBUTE: UnitPrice ATTR VALUE: 39.95 END ATTRIBUTE: UnitPrice START ATTRIBUTE: Quantity ATTR VALUE: 2 END ATTRIBUTE: Quantity END ELEMENT: Part END ELEMENT: LineItem . . . END ELEMENT: LineItems END ELEMENT: PurchaseOrder END DOCUMENT
親トピック: C DOM API for XMLType
14.8 Cでの一般的なXMLType操作
一般的なXML操作は、C API for XMLによって提供されます。
表14-2に、一般的なXML操作のXMLType
関数を示します。
表14-2 Cでの一般的なXMLType操作
説明 | C API XMLType関数 |
---|---|
空の |
|
ソース・バッファからの作成 |
|
XPath式の抽出 |
|
XSLTスタイルシートを使用した変換 |
|
XPathの存在チェック |
|
スキーマベースの文書かどうかのチェック |
|
スキーマ情報の取得 |
|
文書の名前空間の取得 |
|
スキーマを使用した検証 |
|
|
|
DOMからのXMLTypeの取得 |
|
関連項目:
Oracle XML Developer's Kitプログラマーズ・ガイドの「XML Parser for C」
例14-4では、DOMを使用して、発注された特定部品のインスタンスの数を判別する方法を示します。対象となる部品は、Id
37429158722
です。ヘルパー関数exec_bind_xml
、free_oci_handles
およびinit_oci_handles
の定義は、Oracleが提供するXML Schemaおよび例の例A-6を参照してください。
例14-4 DOMを使用した発注部品のカウント
#ifndef S_ORACLE #endif #ifndef ORATYPES_ORACLE #include <oratypes.h> #endif #ifndef XML_ORACLE #include <xml.h> #endif #ifndef OCIXML_ORACLE #include <ocixml.h> #endif #ifndef OCI_ORACLE #include <oci.h> #endif #include <string.h> typedef struct test_ctx { OCIEnv *envhp; OCIError *errhp; OCISvcCtx *svchp; OCIStmt *stmthp; OCIServer *srvhp; OCIDuration dur; OCISession *sesshp; oratext *username; oratext *password; } test_ctx; /* Helper function 1: execute a sql statement which binds xml data */ static sword exec_bind_xml(OCISvcCtx *svchp, OCIError *errhp, OCIStmt *stmthp, void *xml, OCIType *xmltdo, OraText *sqlstmt); /* Helper function 2: Initialize OCI handles and connect */ static sword init_oci_handles(test_ctx *ctx); /* Helper function 3: Free OCI handles and disconnect */ static sword free_oci_handles(test_ctx *ctx); void main() { test_ctx temp_ctx; test_ctx *ctx = &temp_ctx; OCIType *xmltdo = (OCIType *) 0; xmldocnode *doc = (xmldocnode *)0; ocixmldbparam params[1]; xmlnode *quux, *foo, *foo_data, *top; xmlerr err; sword status = 0; xmlctx *xctx; ub4 xmlsize = 0; OCIDefine *defnp = (OCIDefine *) 0; oratext sel_stmt[] = "SELECT SYS_NC_ROWINFO$ FROM PURCHASEORDER"; xmlnodelist *litems = (xmlnodelist *)0; xmlnode *item = (xmlnode *)item; xmlnode *part; xmlnamedmap *attrs; xmlnode *id; xmlnode *qty; oratext *idval; oratext *qtyval; ub4 total_qty; int i; int numdocs; ctx->username = (oratext *)"oe"; ctx->password = (oratext *)"***********"; /* Replace with real password */ /* Initialize envhp, svchp, errhp, dur, stmthp */ init_oci_handles(ctx); /* Get an xml context */ params[0].name_ocixmldbparam = XCTXINIT_OCIDUR; params[0].value_ocixmldbparam = &ctx->dur; xctx = OCIXmlDbInitXmlCtx(ctx->envhp, ctx->svchp, ctx->errhp, params, 1); /* Start processing */ printf("\n\nSupports XML 1.0? : %s\n", XmlHasFeature(xctx, (oratext *) "xml", (oratext *) "1.0") ? "YES" : "NO"); /* Get the documents from the database using a select statement */ status = OCITypeByName(ctx->envhp, ctx->errhp, ctx->svchp, (const text *) "SYS", (ub4) strlen((char *)"SYS"), (const text *) "XMLTYPE", (ub4) strlen((char *)"XMLTYPE"), (CONST text *) 0, (ub4) 0, OCI_DURATION_SESSION, OCI_TYPEGET_HEADER, (OCIType **) &xmltdo); status = OCIStmtPrepare(ctx->stmthp, ctx->errhp, (CONST OraText *)sel_stmt, (ub4) strlen((char *)sel_stmt), (ub4) OCI_NTV_SYNTAX, (ub4) OCI_DEFAULT); status = OCIDefineByPos(ctx->stmthp, &defnp, ctx->errhp, (ub4) 1, (dvoid *) 0, (sb4) 0, SQLT_NTY, (dvoid *) 0, (ub2 *)0, (ub2 *)0, (ub4) OCI_DEFAULT); status = OCIDefineObject(defnp, ctx->errhp, (OCIType *) xmltdo, (dvoid **) &doc, &xmlsize, (dvoid **) 0, (ub4 *) 0); status = OCIStmtExecute(ctx->svchp, ctx->stmthp, ctx->errhp, (ub4) 0, (ub4) 0, (CONST OCISnapshot*) 0, (OCISnapshot*) 0, (ub4) OCI_DEFAULT); /* Initialize variables */ total_qty = 0; numdocs = 0; /* Loop through all the documents */ while ((status = OCIStmtFetch2(ctx->stmthp, ctx->errhp, (ub4) 1, (ub4) OCI_FETCH_NEXT, (ub4)1, (ub4) OCI_DEFAULT)) == 0) { numdocs++; /* Get all the LineItem elements */ litems = XmlDomGetDocElemsByTag(xctx, doc, (oratext *)"LineItem"); i = 0; /* Loop through all LineItems */ while (item = XmlDomGetNodeListItem(xctx, litems, i)) { /* Get the part */ part = XmlDomGetLastChild(xctx, item); /* Get the attributes */ attrs = XmlDomGetAttrs(xctx, (xmlelemnode *)part); /* Get the id attribute and its value */ id = XmlDomGetNamedItem(xctx, attrs, (oratext *)"Id"); idval = XmlDomGetNodeValue(xctx, id); /* Keep only parts with id 37429158722 */ if (idval && (strlen((char *)idval) == 11 ) && !strncmp((char *)idval, (char *)"37429158722", 11)) { /* Get the quantity attribute and its value.*/ qty = XmlDomGetNamedItem(xctx, attrs, (oratext *)"Quantity"); qtyval = XmlDomGetNodeValue(xctx, qty); /* Add the quantity to total_qty */ total_qty += atoi((char *)qtyval); } i++; } XmlFreeDocument(xctx, doc); doc = (xmldocnode *)0; } printf("Total quantity needed for part 37429158722 = %d\n", total_qty); printf("Number of documents in table PURCHASEORDER = %d\n", numdocs); /* Free Xml Ctx */ OCIXmlDbFreeXmlCtx(xctx); /* Free envhp, svchp, errhp, stmthp */ free_oci_handles(ctx); }
このCプログラムのコンパイルおよび実行からの出力は、次のとおりです。
Supports XML 1.0? : YES Total quantity needed for part 37429158722 = 42 Number of documents in table PURCHASEORDER = 132
親トピック: C DOM API for XMLType