| Oracle9i XML Database Developer's Guide - Oracle XML DB Release 2 (9.2) Part Number A96620-02 |
|
|
View PDF |
This chapter describes how to use XMLType in Java, including fetching XMLType data through JDBC.
Oracle XML DB supports the Java Document Object Model (DOM) API for XMLType. This is a generic API for client and server, for both XML schema-based and non- schema-based documents. It is implemented using the Java package oracle.xdb.dom.
To access XMLType data using JDBC use the class oracle.xdb.XMLType.
For XML documents that do not conform to any XML schema, you can use the Java DOM API for XMLType as it can handle any valid XML document.
Java DOM API for XMLType handles all kinds of valid XML documents irrespective of how they are stored in Oracle XML DB. It presents to the application a uniform view of the XML document irrespective of whether it is XML schema-based or non- schema-based, whatever the underlying storage. Java DOM API works on client and server.
As discussed in Chapter 8, "PL/SQL API for XMLType", the Oracle XML DB DOM APIs are compliant with W3C DOM Level 1.0 and Level 2.0 Core Recommendation.
Oracle XML DB Resource API for Java API allows Java applications to access XML documents stored in the Oracle XML DB Repository. Naming conforms to the Java binding for DOM as specified by the W3C DOM Recommendation. Oracle XML DB Repository hierarchy can store both XML schema-based and non- schema-based documents.
Oracle XML DB provides the following way (part of the Java Resource APIs) for Java applications to access XML data stored in a database:
This is an SQL-based approach for Java applications for accessing any data in Oracle9i database, including XML documents in Oracle XML DB. Use the oracle.xdb.dom.XMLType class, createXML() method.
JDBC users can query an XMLType table to obtain a JDBC XMLType interface that supports all methods supported by the SQL XMLType data type. The Java (JDBC) API for XMLType interface can implement the DOM document interface.
The following is an example that illustrates using JDBC to query an XMLType table:
import oracle.xdb.XMLType; ... OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement("select e.poDoc from po_xml_tab e"); ResultSet rset = stmt.executeQuery(); OracleResultSet orset = (OracleResultSet) rset; while(orset.next()) { // get the XMLType XMLType poxml = XMLType.createXML(orset.getOPAQUE(1)); // get the XMLDocument as a string... Document podoc = (Document)poxml.getDOM(); }
You can select the XMLType data in JDBC in one of two ways:
getClobVal() or getStringVal() in SQL and get the result as a oracle.sql.CLOB or java.lang.String in Java. The following Java code snippet shows how to do this:
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection conn = DriverManager.getConnection("jdbc:oracle:oci8:@", "scott", "tiger"); OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "select e.poDoc.getClobVal() poDoc, "+ "e.poDoc.getStringVal() poString "+ " from po_xml_tab e"); ResultSet rset = stmt.executeQuery(); OracleResultSet orset = (OracleResultSet) rset; while(orset.next()) { // the first argument is a CLOB oracle.sql.CLOB clb = orset.getCLOB(1); // the second argument is a string.. String poString = orset.getString(2); // now use the CLOB inside the program }
getOPAQUE() call in the PreparedStatement to get the whole XMLType instance, and use the XMLType constructor to construct an oracle.xdb.XMLType class out of it. Then you can use the Java functions on the XMLType class to access the data.
import oracle.xdb.XMLType; ... OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "select e.poDoc from po_xml_tab e"); ResultSet rset = stmt.executeQuery(); OracleResultSet orset = (OracleResultSet) rset; // get the XMLType XMLType poxml = XMLType(orset.getOPAQUE(1)); // get the XML as a string... String poString = poxml.getStringVal();
This example shows the use of getObject to directly get the XMLType from the ResultSet. This is the easiest way to get the XMLType from the ResultSet.
import oracle.xdb.XMLType; ... OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "select e.poDoc from po_xml_tab e"); ResultSet rset = stmt.executeQuery(); OracleResultSet orset = (OracleResultSet) rset; while(orset.next()) { // get the XMLType XMLType poxml = (XMLType)orset.getObject(1); // get the XML as a string... String poString = poxml.getStringVal(); }
You can also update, insert, and delete XMLType data using JDBC.
You can insert an XMLType in java in one of two ways:
INSERT/UPDATE/DELETE statement, and use the XMLType constructor inside SQL to construct the XML instance:
OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "update po_xml_tab set poDoc = XMLType(?) "); // the second argument is a string.. String poString = "<PO><PONO>200</PONO><PNAME>PO_2</PNAME></PO>"; // now bind the string.. stmt.setString(1,poString); stmt.execute();
setObject() (or setOPAQUE()) call in the PreparedStatement to set the whole XMLType instance:
import oracle.xdb.XMLType; ... OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "update po_xml_tab set poDoc = ? "); // the second argument is a string String poString = "<PO><PONO>200</PONO><PNAME>PO_2</PNAME></PO>"; XMLType poXML = XMLType.createXML(conn, poString); // now bind the string.. stmt.setObject(1,poXML); stmt.execute();
When selecting out XMLType values, JDBC describes the column as an OPAQUE type. You can select the column type name out and compare it with "XMLTYPE" to check if you are dealing with an XMLType:
import oracle.sql.*; import oracle.jdbc.*; ... OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "select poDoc from po_xml_tab"); OracleResultSet rset = (OracleResultSet)stmt.exuecuteQuery(); // Now, we can get the resultset metadata OracleResultSetMetaData mdata = (OracleResultSetMetaData)rset.getMetaData(); // Describe the column = the column type comes out as OPAQUE // and column type name comes out as XMLTYPE if (mdata.getColumnType(1) == OracleTypes.OPAQUE && mdata.getColumnTypeName(1).compareTo("SYS.XMLTYPE") == 0) { // we know it is an XMLtype }
This example updates the discount element inside PurchaseOrder stored in an XMLType column. It uses Java (JDBC) and the oracle.xdb.XMLType class. This example also shows you how to insert/update/delete XMLTypes using Java (JDBC). It uses the parser to update an in-memory DOM tree and write the updated XML value to the column.
-- create po_xml_hist table to store old PurchaseOrders create table po_xml_hist ( xpo xmltype ); /* DESCRIPTION Example for oracle.xdb.XMLType NOTES Have classes12.zip, xmlparserv2.jar, and oraxdb.jar in CLASSPATH */ import java.sql.*; import java.io.*; import oracle.xml.parser.v2.*; import org.xml.sax.*; import org.w3c.dom.*; import oracle.jdbc.driver.*; import oracle.sql.*; import oracle.xdb.XMLType; public class tkxmtpje { static String conStr = "jdbc:oracle:oci8:@"; static String user = "scott"; static String pass = "tiger"; static String qryStr = "SELECT x.poDoc from po_xml_tab x "+ "WHERE x.poDoc.extract('/PO/PONO/text()').getNumberVal()=200"; static String updateXML(String xmlTypeStr) { System.out.println("\n==============================="); System.out.println("xmlType.getStringVal():"); System.out.println(xmlTypeStr); System.out.println("==============================="); String outXML = null; try{ DOMParser parser = new DOMParser(); parser.setValidationMode(false); parser.setPreserveWhitespace (true); parser.parse(new StringReader(xmlTypeStr)); System.out.println("xmlType.getStringVal(): xml String is well-formed"); XMLDocument doc = parser.getDocument(); NodeList nl = doc.getElementsByTagName("DISCOUNT"); for(int i=0;i<nl.getLength();i++){ XMLElement discount = (XMLElement)nl.item(i); XMLNode textNode = (XMLNode)discount.getFirstChild(); textNode.setNodeValue("10"); } StringWriter sw = new StringWriter(); doc.print(new PrintWriter(sw)); outXML = sw.toString(); //print modified xml System.out.println("\n==============================="); System.out.println("Updated PurchaseOrder:"); System.out.println(outXML); System.out.println("==============================="); } catch ( Exception e ) { e.printStackTrace(System.out); } return outXML; } public static void main(String args[]) throws Exception { try{ System.out.println("qryStr="+ qryStr); DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection conn = DriverManager.getConnection("jdbc:oracle:oci8:@", user, pass); Statement s = conn.createStatement(); OraclePreparedStatement stmt; ResultSet rset = s.executeQuery(qryStr); OracleResultSet orset = (OracleResultSet) rset; while(orset.next()){ //retrieve PurchaseOrder xml document from database XMLType xt = XMLType.createXML(orset.getOPAQUE(1)); //store this PurchaseOrder in po_xml_hist table stmt = (OraclePreparedStatement)conn.prepareStatement( "insert into po_xml_hist values(?)"); stmt.setObject(1,xt); // bind the XMLType instance stmt.execute(); //update "DISCOUNT" element String newXML = updateXML(xt.getStringVal()); // create a new instance of an XMLtype from the updated value xt = XMLType.createXML(conn,newXML); // update PurchaseOrder xml document in database stmt = (OraclePreparedStatement)conn.prepareStatement( "update po_xml_tab x set x.poDoc =? where "+ "x.poDoc.extract('/PO/PONO/text()').getNumberVal()=200"); stmt.setObject(1,xt); // bind the XMLType instance stmt.execute(); conn.commit(); System.out.println("PurchaseOrder 200 Updated!"); } //delete PurchaseOrder 1001 s.execute("delete from po_xml x"+ "where x.xpo.extract"+ "('/PurchaseOrder/PONO/text()').getNumberVal()=1001"); System.out.println("PurchaseOrder 1001 deleted!"); } catch( Exception e ) { e.printStackTrace(System.out); } } } ---------------------- -- list PurchaseOrders ---------------------- set long 20000 set pages 100 select x.xpo.getClobVal() from po_xml x;
Here is the resulting updated purchase order in XML:
<?xml version = '1.0'?> <PurchaseOrder> <PONO>200</PONO> <CUSTOMER> <CUSTNO>2</CUSTNO> <CUSTNAME>John Nike</CUSTNAME> <ADDRESS> <STREET>323 College Drive</STREET> <CITY>Edison</CITY> <STATE>NJ</STATE> <ZIP>08820</ZIP> </ADDRESS> <PHONELIST> <VARCHAR2>609-555-1212</VARCHAR2> <VARCHAR2>201-555-1212</VARCHAR2> </PHONELIST> </CUSTOMER> <ORDERDATE>20-APR-97</ORDERDATE> <SHIPDATE>20-MAY-97 12.00.00.000000 AM</SHIPDATE> <LINEITEMS> <LINEITEM_TYP LineItemNo="1"> <ITEM StockNo="1004"> <PRICE>6750</PRICE> <TAXRATE>2</TAXRATE> </ITEM> <QUANTITY>1</QUANTITY> <DISCOUNT>10</DISCOUNT> </LINEITEM_TYP> <LINEITEM_TYP LineItemNo="2"> <ITEM StockNo="1011"> <PRICE>4500.23</PRICE> <TAXRATE>2</TAXRATE> </ITEM> <QUANTITY>2</QUANTITY> <DISCOUNT>10</DISCOUNT> </LINEITEM_TYP> </LINEITEMS> <SHIPTOADDR> <STREET>55 Madison Ave</STREET> <CITY>Madison</CITY> <STATE>WI</STATE> <ZIP>53715</ZIP> </SHIPTOADDR> </PurchaseOrder>
This example performs the following:
XMLType from an XMLType tableXMLType based on an XPath expressionXMLType to another XML format based on XSLXMLType document against an XML schema
import java.sql.*; import java.io.*; import java.net.*; import java.util.*; import oracle.xml.parser.v2.*; import oracle.xml.parser.schema.*; import org.xml.sax.*; import org.w3c.dom.*; import oracle.xml.sql.dataset.*; import oracle.xml.sql.query.*; import oracle.xml.sql.docgen.*; import oracle.xml.sql.*; import oracle.jdbc.driver.*; import oracle.sql.*; import oracle.xdb.XMLType; public class tkxmtpk1 { static String conStr = "jdbc:oracle:oci8:@"; static String user = "tpjc"; static String pass = "tpjc"; static String qryStr = "select x.resume from t1 x where id<3"; static String xslStr = "<?xml version='1.0' ?> " + "<xsl:stylesheet version='1.0' xmlns:xsl='http://www.w3.org/1 999/XSL/Transform'> " + "<xsl:template match='ROOT'> " + "<xsl:apply-templates/> " + "</xsl:template> " + "<xsl:template match='NAME'> " + "<html> " + " <body> " + " This is Test " + " </body> " + "</html> " + "</xsl:template> " + "</xsl:stylesheet>"; static void parseArg(String args[]) { conStr = (args.length >= 1 ? args[0]:conStr); user = (args.length >= 2 ? args[1].substring(0, args[1].indexOf("/")):user); pass = (args.length >= 2 ? args[1].substring(args[1].indexOf("/")+1):pass); qryStr = (args.length >= 3 ? args[2]:qryStr); } /** * Print the byte array contents */ static void showValue(byte[] bytes) throws SQLException { if (bytes == null) System.out.println("null"); else if (bytes.length == 0) System.out.println("empty"); else { for(int i=0; i<bytes.length; i++) System.out.print((bytes[i]&0xff)+" "); System.out.println(); } } public static void main(String args[]) throws Exception { tkxmjnd1 util = new tkxmjnd1(); try{ if( args != null ) parseArg(args); // System.out.println("conStr=" + conStr); System.out.println("user/pass=" + user + "/" +pass ); System.out.println("qryStr="+ qryStr); DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection conn = DriverManager.getConnection(conStr, user, pass); Statement s = conn.createStatement(); ResultSet rset = s.executeQuery(qryStr); OracleResultSet orset = (OracleResultSet) rset; OPAQUE xml; while(orset.next()){ xml = orset.getOPAQUE(1); oracle.xdb.XMLType xt = oracle.xdb.XMLType.createXML(xml); System.out.println("Testing getDOM() ..."); Document doc = xt.getDOM(); util.printDocument(doc); System.out.println("Testing getBytesValue() ..."); showValue(xt.getBytesValue()); System.out.println("Testing existsNode() ..."); try { System.out.println("existsNode(/)" + xt.existsNode("/", null)); } catch (SQLException e) { System.out.println("Thin driver Expected exception: " + e); } System.out.println("Testing extract() ..."); try { XMLType xt1 = xt.extract("/RESUME", null); System.out.println("extract RESUME: " + xt1.getStringVal()); System.out.println("should be Fragment: " + xt1.isFragment()); } catch (SQLException e) { System.out.println("Thin driver Expected exception: " + e); } System.out.println("Testing isFragment() ..."); try { System.out.println("isFragment = " + xt.isFragment()); } catch (SQLException e) { System.out.println("Thin driver Expected exception: " + e); } System.out.println("Testing isSchemaValid() ..."); try { System.out.println("isSchemaValid(): " + xt.isSchemaValid(null,"RES UME")); } catch (SQLException e) { System.out.println("Thin driver Expected exception: " + e); } System.out.println("Testing transform() ..."); System.out.println("XSLDOC: \n" + xslStr + "\n"); try { /* XMLType xslDoc = XMLType.createXML(conn, xslStr); System.out.println("XSLDOC Generated"); System.out.println("After transformation:\n" + (xt.transform(xslDoc, null)).getStringVal()); */ System.out.println("After transformation:\n" + (xt.transform(null, null)).getStringVal()); } catch (SQLException e) { System.out.println("Thin driver Expected exception: " + e); } System.out.println("Testing createXML(conn, doc) ..."); try { XMLType xt1 = XMLType.createXML(conn, doc); System.out.println(xt1.getStringVal()); } catch (SQLException e) { System.out.println("Got exception: " + e); } } } catch( Exception e ) { e.printStackTrace(System.out); } } }
When you use the Java DOM API to get XML data from Oracle XML DB, you get an XMLDocument object that represents the XML data or file you retrieve. From this document interface you can get the elements of the document and perform all the operations specified in the W3C DOM specification. The DOM works on:
The Java DOM API for XMLType supports deep or shallow searching in the document to retrieve children and properties of XML objects such as name, namespace, and so on. Conforming to the DOM 2.0 recommendation, Java DOM API for XMLType is namespace aware.
Java API for XMLType also allows applications to create XML documents programmatically. This way applications can create XML documents on the fly (or dynamically) that either conform to a preregistered XML schema or are non-XML schema-based documents.
To create XML schema-based documents, Java DOM API for XMLType uses an extension to specify which XML schema URL to use. For XML schema-based documents, it also verifies that the DOM being created conforms to the specified XML schema, that is, that the appropriate children are being inserted under the appropriate documents.
Once the DOM object has been created, it can be saved to Oracle XML DB Repository using the Oracle XML DB Resource API for Java. The XML document is stored in the appropriate format:
The following example shows how you can use Java DOM API for XMLType to create a DOM object and store it in the format specified by the XML schema. Note that the validation against the XML schema is not shown here.
import oracle.xdb.XMLType; ... OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "update po_xml_tab set poDoc = ? "); // the second argument is a string String poString = "<PO><PONO>200</PONO><PNAME>PO_2</PNAME></PO>"; XMLType poXML = XMLType.createXML(conn, poString); Document poDOM = (Document)poXML.getDOM(); Element rootElem = poDOM.createElement("PO"); poDOM.insertBefore(poDOM, rootElem, null); // now bind the string.. stmt.setObject(1,poXML); stmt.execute();
An XMLType instance is represented in Java by oracle.xdb.XMLType. When an instance of XMLType is fetched using JDBC, it is automatically manifested as an object of the provided XMLType class. Similarly, objects of this class can be bound as values to Data Manipulation Language (DML) statements where an XMLType is expected. The same behavior is supported in SQLJ clients.
Oracle XML DB supports the W3C DOM Level 2 Recommendation. In addition to the W3C Recommendation, Oracle XML DB DOM API also provides Oracle-specific extensions, mainly to facilitate your application interfacing with Oracle XDK for Java. A list of the Oracle extensions is found at: http://otn.oracle.com/docs/tech/xml/xdk_java/content.html
XMLDocument() is a class that represents the DOM for the instantiated XML document. You can retrieve the XMLType from the XML document using the function getXMLType() on XMLDocument() class.
Table 9-1 lists the Java DOM API for XMLType classes and the W3C DOM interfaces they implement.
The following are methods documented in Release 2 (9.2.0.1) but not currently supported:
XDBDocument.getElementByIDXDBDocument.importNodeXDBNode.normalizeXDBNode.isSupportedXDBDomImplementation.hasFeatureThe following Java DOM API for XMLType calling sequence description assumes that your XML data is pre-registered with an XML schema and that it is stored in an XMLType datatype column. To use the Java DOM API for XMLType, follow these steps:
XMLType table or XMLType column in the table. When you fetch XML data, Oracle XML DB creates a DOMDocument instance of XMLType, parsing the document into a DOM tree. You can then manipulate elements in the DOM tree using Java DOM API for XMLType.XMLType to perform operations and manipulations on elements of the DOM tree.XMLType sends the changed XML data back to Oracle XML DB.Figure 9-1 illustrates the Java DOM API for XMLType calling sequence.
