Skip Headers

Oracle® XML DB Developer's Guide
10g Release 1 (10.1)

Part Number B10790-01
Go to Documentation Home
Home
Go to Book List
Book List
Go to Table of Contents
Contents
Go to Index
Index
Go to Master Index
Master Index
Go to Feedback page
Feedback

Go to previous page
Previous
Go to next page
Next
View PDF

13 Using C API for XML With Oracle XML DB

This chapter provides a guideline for using the C API for XML with Oracle XML DB.

This chapter contains these topics:


See Also:

Oracle XML Developer's Kit Programmer's Guide "XML Parser for C"

Introducing the C API for XML (XDK and Oracle XML DB)

The C API for XML is used for both XDK (XML Developer's Kit) and Oracle XML DB. It is a C-based DOM API for XML. It can be used for XML either inside or outside the database. Here DOM refers to compliance with the World Wide Web Consortium (W3C) DOM 2.0 Recommendation. This API also includes non-standard performance improving extensions used as follows:


Note:

Use this new C API for XML for any new XDK and Oracle XML DB applications. C DOM functions from prior releases are supported only for backward compatibility, but will not be enhanced.

The C API for XML is implemented on XMLType in Oracle XML DB. In the W3C DOM Recommendation, the term document is used in a broad sense (URI, file system, memory buffer, standard input and output). The C API for XML is a combined programming interface that includes all functionality needed by both XDK and Oracle XML DB applications. It provides for XSLT and XML Schema implementations. Although DOM 2.0 Recommendation was followed closely, some naming changes were required for mapping from the objected-oriented DOM 2.0 Recommendation to the flat C namespace. For example, the method getName() was renamed to getAttrName().

C API for XML supersedes existing APIs. In particular, the oraxml interface (top-level, DOM, SAX, and XSLT) and oraxsd.h (Schema) interfaces will be deprecated in a future release.

Using OCI and the C API for XML with Oracle XML DB

Oracle XML DB provides support for storing and manipulating XML instances using the XMLType datatype. These XML instances can be accessed and manipulated using the Oracle Call Interface (OCI) in conjunction with the C DOM API for XML.

The main flow for an application program would involve initializing the usual OCI handles such as server handle and statement handle followed by initialization of an XML Context. The user program can then either operate on XML instances in the back end or create new instances on the client side. The initialized XML context can be used with all the C DOM functions.

XML data stored in Oracle XML DB can be accessed on the client side using the C DOM structure xmldocnode. This structure can be used for binding, defining and operating on XML values in OCI statements.

XML Context

An XML context is a required parameter to all the C DOM API functions. This context encapsulates information pertaining to data encoding, error message language and such. This contents of this opaque context are different for XDK applications and Oracle XML DB.

For Oracle XML DB, there are two OCI functions provided to initialize an XML context. The function OCIXmlDbInitXmlCtx() is used to initialize the context while OCIXmlDbFreeXmlCtx() tears it down.

OCIXmlDbFreeXmlCtx() Syntax

Here is the OCIXmlDbFreeXmlCtx() syntax:

void OCIXmlDbFreeXmlCtx ( xmlctx *xctx);

where parameter, xctx (IN) is the XML context to terminate.

OCIXmlDbInitXmlCtx() Syntax

Here is the OCIXmlDbInitXmlCtx() syntax:

xmlctx *OCIXmlDbInitXMlCtx (  OCIEnv                *envhp,
                              OCISvcHp              *svchp,
                              OCIError              *errhp,
                              ocixmldbparam         *params,
                              ub4                   num_params );

where Table 13-1 lists the parameters.

Table 13-1 OCIXmlDbInitXMlCtx Parameters

Parameter Description
envhp (IN) The OCI environment handle.
svchp (IN) The OCI service handle.
errhp (IN) The OCI error handle
params (IN) Optional values in this array as follows:

OCI duration. Default value is OCI_DURATION_SESSION.An error handler which is a user-registered callback of prototype:

void (*err_handler) (sword errcode, (CONST OraText *)
 errmsg);void (*err_handler) (sword errcode, 
(CONST OraText *) errmsg);
num_params (IN)
Number of parameters to be read from params.

How to Use Oracle XML DB Functions

In Oracle XML DB, to initialize and terminate the XML context, use the functions OCIXmlDbInitXmlCtx() and OCIXmlDbFreeXmlCtx(), respectively, as shown in the following example. These examples are found in header file ocixmldb.h and used with the C API for XML:

Example 13-1 Using OCI and C API for XML with Oracle XML DB

#ifndef XML_ORACLE
#include <xml.h>
#endif

#ifndef OCIXML_ORACLE
#include <ocixml.h>
#endif

#ifndef OCI_ORACLE
#include <oci.h>
#endif
...

typedef enum {
   XCTXINIT_OCIDUR = 1,
   XCTXINIT_ERRHDL = 2
} ocixmldbpname;

typdef struct ocixmldbparam {
  ociXmlDbPName name_ocixml dbpname;
  void *value_ocixmldbparam;
} ocixmldbparam;

The following code shows how to perform operations with the C API for XML:

{
OCIStmt *stmthp = (OCIStmt *)0;
xmlctx *xctx = (xmlctx *)0;
ocixmldbparam params[NUM_PARAMS];
OCIType *xmltdo = (OCIType *)0;
OCIDuration dur = OCI_DURATION_SESSION;
text *sel_xml_stmt = (text*)"SELECT xml_col FROM tkpgxucm_tab";
OraText *xpathexpr = (OraText *)"/name";
sword status = 0;

/* Allocate statement handle for SQL executions */
if (status=OCIHandleAlloc((dvoid *)ctxptr->envhp, (dvoid **)&stmthp,
                          (ub4)OCI_HTYPE_STMT, (CONST size_t)0, (dvoid **)0))
{
 
   return OCI_ERROR;
}
 
/* Get an XML context */
params[0].name_xmlctx_param = XCTXINIT_OCIDUR;
params[0].value_xmlctx_param = &dur;
 
/* Initialize an XML context */
xctx = OCIXmlDbInitXMlCtx (ctxptr->envhp, ctxptr->svchp, ctxptr->errhp, 
       params, 1);
 
/* Do unified C API operations next */
...
 
/* Free the allocations associated with the context */
OCIXmlDbFreeXMlCtx(xctx);
}

OCI Usage

OCI applications operating on XML typically operate on XML data stored in the server and also on XML data created on the client. This section explains these two access methods in more detail.

Accessing XMLType Data From the Back End

XML data on the server can be operated on the client using regular OCI statement calls. Similar to other object instances, users can bind and define XMLType values using xmldocnode. OCI statements can be used to select XML data from the server and this can be used in the C DOM functions directly. Similarly, the values can be bound back to SQL statements directly.

Creating XMLType Instances on the Client

New XMLType instances on the client can be constructed using the XmlLoadDom() calls. You first have to initialize the xmlctx as in the preceding example. The XML data itself can be constructed from a user buffer, local file, or URI. The return value from these is a (xmldocnode *) that can be used in the rest of the common C API. Finally, the (xmldocnode *) can be cast to a (void*) and directly provided as the bind value if required.Empty XMLType instances can be constructed using the XMLCreateDocument() call. This would be equivalent to an OCIObjectNew() for other types. You can operate on the (xmldocnode*) returned by the preceding call and finally cast it to a (void*) if it needs to be provided as a bind value.

Common XMLType Operations in C

Table 13-2 provides the XMLType functional equivalent of common XML operations.

Table 13-2 Common XMLType Operations in C

Description C API XMLType Function
Create empty XMLType instance XmlCreateDocument()
Create from a source buffer XmlLoadDom()
Extract an XPath expression XmlXPathEvalexpr() and family
Transform using an XSLT style sheet XmlXslProcess() and family
Check if an XPath exists XmlXPathEvalexpr() and family
Is document schema-based? XmlDomIsSchemaBased()
Get schema information XmlDomGetSchema()
Get document namespace XmlDomGetNodeURI()
Validate using schema XmlSchemaValidate()
Obtain DOM from XMLType Cast (void *) to (xmldocnode *)
Obtain XMLType from DOM Cast (xmldocnode *) to (void *)


See Also:

Oracle XML Developer's Kit Programmer's Guide "XML Parser for C"

Example 13-2 Constructing an XML Schema-Based Document Using DOM API and Saving it to Oracle Database

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 = (OCIType *) 0;
xmldocnode *doc;
ocixmldbparam params[1];
xmlnode *quux, *foo, *foo_data;
xmlerr err;
sword status = 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 */
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;
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;
}

Example 13-3 Retrieving a Document From Oracle Database and Modifying it Using the DOM API

sword example2()
{
OCIEnv *envhp;
OCIError *errhp;
OCISvcCtx *svchp;
OCIStmt *stmthp;
OCIDuration dur;
OCIType *xmltdo_p=(OCIType *) 0;;
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;}