Java DOM API for XMLType
では、DOMを使用してXMLType
インスタンスを操作できます。これを使用すると、Java Database Connectivity (JDBC)を介してXMLデータをフェッチするなど、JavaでXMLデータを操作できます。
Oracle XML DBはJava Document Object Model (DOM) Application Program Interface (API) for XMLType
をサポートします。これはXML Schemaに基づく文書とスキーマに基づかない文書の両方に対する、クライアントおよびサーバー用の汎用APIです。
DOMは、XML文書のメモリー内ツリーベースのオブジェクト表現で、要素および属性へのプログラム・アクセスを可能にします。DOMオブジェクトおよびインタフェースは、W3C勧告の一部です。 PL/SQL API for XMLTypeで説明したとおり、Oracle XML DB DOM APIは、W3CのDOMレベル1.0およびレベル2.0のコア勧告に準拠しています。
Java DOM API for XMLType
では、Oracle XML DBに格納されたすべての整形式のXML文書を処理します。XML文書は、XML Schemaに基づくかどうか、および基礎となるXMLType
記憶域モデルの形式に関係なく、同様に表示されます。Java DOM APIは、クライアントおよびサーバーの両方で動作します。
Java DOM API for XMLType
を使用すると、別のキャラクタ・セットでエンコードされたデータからXMLType
インスタンスを作成できます。
Java DOM API for XMLType
を使用して、JavaアプリケーションからOracle XML DBリポジトリに格納されたXML文書にアクセスできます。ネーミングは、W3CのDOM勧告で指定されている、DOMへのJavaバインディングに準拠しています。リポジトリには、XML Schemaに基づくドキュメントおよび基づかないドキュメントの両方を含めることができます。
JDBCを使用してXMLType
データにアクセスするには、クラスoracle.xdb.XMLType
を使用します。
Java DOM API for XMLType
は、Javaパッケージoracle.xml.parser.v2
を使用して実装されます。
関連項目:
『Oracle Database XML Java API Reference』
Java Database Connectivity (JDBC)は、Oracle XML DB内のXML文書など、Oracle Database内のすべてのデータにアクセスするための、Javaアプリケーション用のSQLベースの方法です。
XMLデータを作成するには、oracle.xdb.XMLType
JavaクラスのcreateXML()
メソッドを使用します。
注意:
入力としてストリームを引き渡す場合は、メソッドXMLType.createXML()
とThickドライバを使用してください。この場合、Thinドライバは使用できません。
XMLデータのJDBC 4.0標準データ型はjava.sql.SQLXML
です。getObject()
メソッドでは、oracle.xdb.XMLType
型のオブジェクトが戻されます。Oracle Database 11gリリース2 (11.2.0.3)から、oracle.xdb.XMLType
がインタフェースjava.sql.SQLXML
を実装しています。
JDBCユーザーは、XMLType
表を問い合せて、SQL XMLType
データ型でサポートされるすべてのSQL/XML関数をサポートするJDBC XMLType
インタフェースを取得できます。Java(JDBC)API for XMLType
インタフェースは、DOMDocumentインタフェースを実装できます。
例13-1に、JDBCを使用してXMLType
表を問い合せる方法を示します。
次のいずれかの方法で、JDBCを使用してXMLType
データを選択できます。
SQLでSQL/XML関数XMLSerialize
を使用し、Javaでoracle.sql.CLOB
、java.lang.String
またはoracle.sql.BLOB
として結果を取得します。例13-2のJavaスニペットに、これを示します。
PreparedStatementでメソッド
getObject()
をコールして、XMLType
インスタンス全体を取得します。このメソッドの戻り値は、oracle.xdb.XMLType
型です。これによって、XMLType
クラスでJava関数を使用して、データにアクセスできます。この方法を例13-3に示します。
例13-3では、getObject()
メソッドを使用してResultSet
からXMLType
インスタンスを直接取得します。
例13-4では、XMLType
型の出力パラメータをSQL文にバインドします。この出力パラメータは、XMLType
データ型として登録されます。
例13-1 JDBCを使用したXMLType表の問合せ
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 XMLDocument as a string...
Document podoc = (Document)poxml.getDOM();
}
例13-2 getStringVal()およびgetCLOB()を使用したXMLTypeデータの選択
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver()); Connection conn = DriverManager.getConnection("jdbc:oracle:oci8:@", "QUINE", "CURRY"); OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "SELECT XMLSerialize(DOCUMENT e.poDoc AS CLOB) poDoc, " + "XMLSerialize(DOCUMENT e.poDoc AS VARCHAR2(2000)) 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 }
例13-3 getObject()を使用してXMLTypeデータを戻す方法
import oracle.xdb.XMLType;
...
PreparedStatement stmt = conn.prepareStatement(
"SELECT e.poDoc FROM po_xml_tab e");
ResultSet rset = stmt.executeQuery();
while(rset.next())
{
// get the XMLType
XMLType poxml = (XMLType)rset.getObject(1);
// get the XML as a string...
String poString = poxml.getStringVal();
}
例13-4 出力パラメータを使用してXMLTypeデータを戻す方法
public void doCall (String[] args) throws Exception { // CREATE OR REPLACE FUNCTION getPurchaseOrder(reference VARCHAR2) // RETURN XMLTYPE // AS // xml XMLTYPE; // BEGIN // SELECT OBJECT_VALUE INTO xml // FROM purchaseorder // WHERE XMLCast(XMLQuery('$p/PurchaseOrder/Reference' // PASSING OBJECT_VALUE AS "p" RETURNING CONTENT) // AS VARCHAR2(30)) // = reference; // RETURN xml; // END; String SQLTEXT = "{? = call getPurchaseOrder('BLAKE-2002100912333601PDT')}"; CallableStatement sqlStatement = null; XMLType xml = null; super.doSomething(args); createConnection(); try { System.out.println("SQL := " + SQLTEXT); sqlStatement = getConnection().prepareCall(SQLTEXT); sqlStatement.registerOutParameter (1, OracleTypes.OPAQUE,"SYS.XMLTYPE"); sqlStatement.execute(); xml = (XMLType) sqlStatement.getObject(1); System.out.println(xml.getStringVal()); } catch (SQLException SQLe) { if (sqlStatement != null) { sqlStatement.close(); throw SQLe; } } }
Oracle XML DBでJava Database Connectivity (JDBC)を使用して、データベースに格納されたXMLType
データを更新、挿入および削除できます。
注意:
XMLType
メソッドのextract()
、transform()
およびexistsNode()
は、OCIドライバでのみ機能します。
Thin JDBCドライバでは、すべてのoracle.xdb.XMLType関数がサポートされているわけではありません。
oracle.xdb.XMLType
クラスとOCIドライバを使用しない場合、XMLのインテリジェント処理に関連したパフォーマンスのメリットを失う可能性があります。
XMLType
データを次のいずれかの方法で、更新、挿入または削除できます。
CLOB
または文字列をINSERT
、UPDATE
またはDELETE
文にバインドし、SQL内でXMLType
コンストラクタを使用してXMLインスタンスを作成します。例13-5に、これを示します。
PreparedStatementで
setObject()
を使用して、XMLType
インスタンス全体を設定します。例13-6に、これを示します。
XMLType
値を選択すると、JDBCによって、列が不透明型として記述されます。列型の名前を選択し、それをXMLTYPE
と比較すると、XMLType
インスタンスを処理しているかどうかを確認できます。例13-7に、これを示します。
例13-8では、XMLType
列に格納されているPurchaseOrder
要素内のdiscount
要素を更新します。ここではJDBCおよびoracle.xdb.XMLType
クラスを使用します。XMLパーサーを使用してDOMツリーを更新し、更新されたXML値をXMLType
列に書き込みます。
例13-9は、例13-8から得られる更新済の発注書を示します。
例13-10では、次のものがすべて処理されます。
XMLType
表からのXMLType
インスタンスの選択
XPath式に基づくXMLType
インスタンスの一部の抽出
要素の有無の確認
XSLに基づく別のXML形式へのXMLType
インスタンスの変換
XML Schemaに対するXMLType
文書の妥当性の確認
例13-5 SQL UPDATEとコンストラクタXMLTypeを使用したXMLTypeデータの更新
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();
例13-6 SQL UPDATEとsetObject()を使用したXMLTypeデータの更新
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();
例13-7 JDBCを使用したXMLTypeデータに関するメタデータの取得
import oracle.sql.*; import oracle.jdbc.*; ... OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "SELECT poDoc FROM po_xml_tab"); OracleResultSet rset = (OracleResultSet)stmt.executeQuery(); // 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) { // It is an XMLtype instance }
例13-8 JDBCを使用したXMLType列の要素の更新
-- Create po_xml_hist table to store old PurchaseOrders CREATE TABLE po_xml_hist (xpo XMLType); /* NOTE: You must have xmlparserv2.jar and xdb.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 = "QUINE"; static String pass = "CURRY"; static String qryStr = "SELECT x.poDoc from po_xml_tab x " + "WHERE XMLCast(XMLQuery('/PO/PONO/text()'" + " PASSING x.poDoc RETURNING CONTENT)" + " AS NUMBER)" + " = 200"; static String updateXML(String xmlTypeStr) Java DOM API for XMLType Beta Draft Java DOM API for XMLType 15-7 { 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)orset.getObject(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 " + "XMLCast(XMLQuery('/PO/PONO/text()'" + " PASSING value(xmltab) RETURNING CONTENT)" + " AS NUMBER)" + "= 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" + "XMLCast(XMLQuery('/PurchaseOrder/PONO/text()'" + " PASSING value(xmltab) RETURNING CONTENT)" + " AS NUMBER)" + "= 1001"); System.out.println("PurchaseOrder 1001 deleted!"); } catch(Exception e) { e.printStackTrace(System.out); } } SELECT x.xpo.getCLOBVal() FROM po_xml x;
例13-9 更新済の発注書
<?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>
例13-10 JDBCを使用したXMLType列の操作
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()) { oracle.xdb.XMLType xt = (oracle.xdb.XMLType)(orset.getObject(1)); 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); } } }
Java Database Connectivity (JDBC)を使用して大規模なXML文書をデータベースにロードするには、Java CLOB
オブジェクトを使用して文書を保持し、JavaメソッドinsertXML()
を使用して挿入します。
大規模なXML文書(通常4000文字を超える場合)がJDBCのString
オブジェクトを使用してXMLType
の表または列に挿入されると、次のランタイム・エラーが発生します。
"java.sql.SQLException: Data size bigger than max size for this type"
このエラーは、JavaのCLOB
オブジェクトを使用して大規模なXML文書を保持することで回避できます。例13-11に、このテクニックを使用するコードを示します。これはXMLType
メソッドのinsertXML()
を定義します。これを使用して、大規模なXML文書が表poTable
のXMLType
の列purchaseOrder
に挿入されます。XMLType
表の場合も同じ方法を使用できます。
メソッドinsertXML()
はXML文書を含むCLOB
オブジェクトを使用します。CLOB
オブジェクトは、クライアント側でクラスoracle.sql.CLOB
を使用して作成されます。このクラスは、Oracle JDBC Driverによる標準JDBCインタフェースjava.sql.Clob
の実装です。メソッドinsertXML()
はCLOB
オブジェクトをJDBCのプリコンパイルされたSQL文にバインドします。これによりデータがXMLType
列に挿入されます。
insertXML()
を使用するための前提条件は、次のとおりです。
Oracle Databaseがリリース9.2.0.1以上であること。
ターゲット・データベース表が存在すること。例を実行する前に、次のSQLを実行してください。
CREATE TABLE poTable (purchaseOrder XMLType);
XMLType
メソッドのinsertXML()
の仮パラメータは、次のとおりです。
xmlData
- XMLType
列に挿入するXMLデータ
conn
- データベース接続オブジェクト(Oracle Connection Object)
JavaメソッドinsertXML()
は、メソッドgetCLOB()
をコールして、XMLデータを格納するCLOB
オブジェクトを作成して戻します。getCLOB()
メソッドの仮パラメータは例13-12で定義され、次のとおりです。
xmlData
- XMLType
列に挿入するXMLデータ
conn
- データベース接続オブジェクト(Oracle Connection Object)
関連項目:
『Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイド』
例13-11 JavaメソッドinsertXML()
... import oracle.sql.CLOB; import java.sql.Connection; import java.sql.SQLException; import java.sql.PreparedStatement; ... private void insertXML(String xmlData, Connection conn) { CLOB clob = null; String query; // Initialize statement Object PreparedStatement pstmt = null; try { query = "INSERT INTO potable (purchaseOrder) VALUES (XMLType(?)) "; // Get the statement Object pstmt = conn.prepareStatement(query); // xmlData is the string that contains the XML Data. // Get the CLOB object. clob = getCLOB(xmlData, conn); // Bind this CLOB with the prepared Statement pstmt.setObject(1, clob); // Execute the Prepared Statement if (pstmt.executeUpdate () == 1) { System.out.println ("Successfully inserted a Purchase Order"); } } catch(SQLException sqlexp) { sqlexp.printStackTrace(); } catch(Exception exp) { exp.printStackTrace(); } }
例13-12 JavaメソッドgetCLOB()
...
import oracle.sql.CLOB;
import java.sql.Connection;
import java.sql.SQLException;
import java.io.Writer;
...
private CLOB getCLOB(String xmlData, Connection conn) throws SQLException
{
CLOB tempClob = null;
try
{
// If the temporary CLOB has not yet been created, create one
tempClob = CLOB.createTemporary(conn, true, CLOB.DURATION_SESSION);
// Open the temporary CLOB in readwrite mode, to enable writing
tempClob.open(CLOB.MODE_READWRITE);
// Get the output stream to write
Writer tempClobWriter = tempClob.getCharacterOutputStream();
// Write the data into the temporary CLOB
tempClobWriter.write(xmlData);
// Flush and close the stream
tempClobWriter.flush();
tempClobWriter.close();
// Close the temporary CLOB
tempClob.close();
}
catch(SQLException sqlexp)
{
tempClob.freeTemporary();
sqlexp.printStackTrace();
}
catch(Exception exp)
{
tempClob.freeTemporary();
exp.printStackTrace();
}
return tempClob;
}
Java DOM API for XMLType
は、XMLオブジェクトの子およびプロパティ(名前、名前空間など)を取得するために、文書内でのディープ検索およびシャロウ検索をサポートします。これにより、アプリケーションはその場で(動的に)作成するなど、XML文書をプログラムで作成できます。そのような文書は、登録されたXML Schemaに準拠することもあれば、しないこともあります。
Java API for XMLType
はDOM 2.0勧告に準拠し、名前空間を認識します。
JavaクラスXMLDocument
およびXDBDocument
(非推奨)は、W3Cドキュメント・オブジェクト・モデル(DOM)・インタフェースのインスタンスです。このドキュメント・インタフェースからドキュメントの要素にアクセスすると、W3CのDOM勧告に指定されたすべての操作を実行できます。DOMは、次のものに対して機能します。
XML Schemaに基づく、基づかないに関係なく、あらゆる種類のXML文書
文書で使用される次のいずれかの形式の基礎となる記憶域
バイナリ・ラージ・オブジェクト(Binary Large Object: BLOB)
オブジェクト・リレーショナル
Java DOM APIを使用してOracle XML DBからXMLデータを取得する場合:
接続がThinの場合は、XML
Document
インスタンスを取得します。
接続がThickまたはkprbの場合は、getDOM()
メソッドでXDB
Document
インスタンスを、getDocument()
メソッドでXML
Document
インスタンスを取得します。getDOM()
メソッドとXDBDocument
クラスは非推奨になりました。
アプリケーションのセキュリティ・ポリシーを実装するためにMS Windows上でJavaセキュリティ・マネージャ(クラスSecurityManager
)を使用する場合は、Thick接続でJava DOM API for XMLType
を使用するために、特定の権限をセキュリティ・ポリシー・ファイルに追加する必要があります。
例13-13では、このようなポリシー・ファイルの内容を示しています。ここで、c:\myworkspace
はOracle XML DBに関連するJARを含むワークスペース・フォルダです。(ポリシー・ファイルは、同じフォルダにある必要があります。)
例13-13で使用しているライブラリは、orageneric12
およびoraxml12
です。最後の2文字(ここでは12
)は、データベースのメジャー・リリース番号に対応している必要があります(したがって、たとえばOracle Database 13 リリース2の場合、orageneric
13
とoraxml
13
を使用します)。
ポリシー・ファイルを作成すると、次のコマンドライン・スイッチを使用してプログラムを呼び出すことができます。
-Djava.security.manager=default -Djava.security.policy=c:\myworkspace\ojdbc.policy
例13-13 Java DOM APIの権限を付与するポリシー・ファイル
grant codeBase "file:c:\myworkspace
" {
permission java.lang.RuntimePermission "loadLibrary.orageneric12";
permission java.lang.RuntimePermission "loadLibrary.oraxml12";
}
grant codeBase "file:c:\myworkspace\xdb6.jar" {
permission java.lang.RuntimePermission "loadLibrary.orageneric12";
permission java.lang.RuntimePermission "loadLibrary.oraxml12";
}
grant codeBase "file:c:\myworkspace\ojdbc6.jar" {
permission java.lang.RuntimePermission "loadLibrary.orageneric12";
permission java.lang.RuntimePermission "loadLibrary.oraxml12";
}
XML Schemaに基づく文書を作成するには、Java DOM API for XMLType
の拡張機能を使用して、使用するXML Schema URLを指定します。また、作成中のDOMが指定されたXML Schemaに準拠するかどうか(適切な子が適切な文書に挿入されているか)も検証します。
注意:
Java DOM API for XMLType
は型および制約のチェックは実行しません。
DOMオブジェクトの作成後は、Oracle XML DB Resource API for Javaを使用して、DOMオブジェクトをOracle XML DBリポジトリに保存できます。XML文書は次の適切な形式で格納されます。
BLOBインスタンス(スキーマに基づかない文書の場合)
XML Schemaで指定された形式(XML Schemaに基づく文書の場合)
例13-14では、Java DOM API for XMLType
を使用してDOMオブジェクトを作成し、関連するXML Schemaで指定された形式で格納します。この例では、XML Schemaに対する検証は示されていません。
例13-14 Java DOM APIを使用したDOMオブジェクトの作成
import oracle.xdb.XMLType; ... OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement( "update po_xml_XMLTypetab 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();
XMLType
インスタンスは、oracle.xdb.XMLType
によってJavaで表現されます。XMLType
インスタンスがJDBCまたはSQLJのクライアントを使用してフェッチされると、このインスタンスは提供されたXMLType
クラスのオブジェクトとして自動的に明示されます。
このクラスのオブジェクトは、データ操作言語(DML)文の値としてバウンドできます。通常、この値はXMLType
です。
Oracle XML DBは、W3CのDOMレベル2勧告をサポートします。また、アプリケーションとOracle XML Developer's Kit for Javaの相互作用を容易にするOracle固有の拡張機能も提供します。Java DOM API for XMLType
では、W3C DOMインタフェースを実装するクラスが提供されます。
Oracleの拡張機能のリストは、次のURLを参照してください。
http://www.oracle.com/technetwork/database-features/xmldb/overview/index.html
XMLDocument
は、インスタンス化されたXML文書用のDOMを表すクラスです。Document
引数を取るXMLType
コンストラクタを使用して、XML文書からXMLType
インスタンスを取得できます。
XMLType createXML(Connection conn, Document domdoc)
表13-1に、Java DOM API for XMLType
のクラスおよび実装されるW3CのDOMインタフェースを示します。Java DOM APIクラスは、oracle.xml.parser.v2
パッケージに入っています。
表13-1 Java DOM API for XMLType: クラス
Java DOM API for XMLTypeのクラス | W3CのDOMインタフェース勧告のクラス |
---|---|
XMLDocument |
org.w3c.dom.Document |
XMLCDATA |
org.w3c.dom.CDataSection |
XMLComment |
org.w3c.dom.Comment |
XMLPI |
org.w3c.dom.ProcessingInstruction |
XMLText |
org.w3c.dom.Text |
XMLEntity |
org.w3c.dom.Entity |
DTD |
org.w3c.dom.DocumentType |
XMLNotation |
org.w3c.dom.Notation |
XMLAttr |
org.w3c.dom.Attribute |
XMLDomImplementation |
org.w3c.dom.DOMImplementation |
XMLElement |
org.w3c.dom.Element |
XMLAttrList |
org.w3c.dom.NamedNodeMap |
XMLNode |
org.w3c.dom.Node |
Oracle Database 11gリリース1より前のリリースで使用されていたXMLType
のJava DOM APIのいくつかのクラスとメソッドは、非推奨になったか、サポートが停止されました。
Oracle Database 9i (9.2.0.1)のマニュアルには次のメソッドに関する説明が含まれていますが、サポートされなくなりました。
XDBDocument.getElementByID
XDBDocument.importNode
XDBNode.normalize
XDBNode.isSupported
XDBDomImplementation.hasFeature
また、Oracle Database 11gリリース1以前は、oracle.xdb.dom
パッケージの異なるAPIがJava DOMに使用されていました。非推奨になったAPIの詳細は、該当リリースのドキュメントを参照してください。oracle.xdb.dom
の次のクラスは、非推奨です。かわりにoracle.xml.parser.v2
クラスを使用してください。
XDBAttribute
- XMLAttr
を使用
XDBBinaryDocument
XDBCData
- XMLCDATA
を使用
XDBComment
- XMLComment
を使用
XDBDocFragment
- XMLDocumentFragment
を使用
XDBDocument
- XMLDocument
を使用
XDBDocumentType
- DTD
を使用
XDBDOMException
- XMLDomException
を使用
XDBDomImplementation
- XMLDomImplementation
を使用
XDBElement
- XMLElement
を使用
XDBEntity
- XMLEntity
を使用
XDBEntityReference
- XMLEntityReference
を使用
XDBNamedNodeMap
- XMLAttrList
を使用
XDBNode
- XMLNode
を使用
XDBNodeList
- NodeList
を使用
XDBNotation
- XMLNotation
を使用
XDBProcInst
- XMLPI
を使用
XDBText
- XMLText
を使用
XMLType
表または列からデータを取得し、そこからJava XMLDocument
インスタンスを取得します。Java DOM API for XMLType
を使用して、データのDOMツリーの要素を操作します。
図13-1に、Java DOM API for XMLType
の使用方法を示します脚注1。次の手順を実行します。
XMLType
表または表のXMLType
列からXMLデータを取り出します。XMLデータをフェッチすると、OracleによってXMLType
インスタンスが作成されます。これにより、getDocument()
メソッドを使用してXMLDocument
インスタンスを取得できます。
Java DOM API for XMLType
を使用してDOMツリーの要素を操作します。変更されたデータはXMLType
インスタンスに格納されますが、データはJDBC更新を使用して戻されます。
XMLType
およびXMLDocument
インスタンスは、各クラスでclose()
メソッドを使用してクローズする必要があります。クローズすると、保持されていた基礎となるメモリーがすべて解放されます。
Oracle XML DBでは、抽象ストリームおよびストリーム操作の各メソッドが提供され、これらを使用して、64 KBを超えるXMLノードを処理できます。Thickまたはkprb接続でJavaクラスXMLNode
およびXMLAttr
を使用して、大規模ノードを操作します。
注意:
大規模ノード機能は、Thickまたはkprb接続でのみ動作します。Thin接続では動作しません。
Oracle Database 11gリリース(11.1)以前は、Oracle XML DBにより処理されるテキスト・ノードまたは属性値のサイズはそれぞれ64KBに制限されていました。リリース11.1以降、この制限はなくなりました。
以前ノードのサイズが制限されていたのは、ノード値を設定および取得するJavaメソッドでjava.lang.String
型の引数のみがサポートされていたためです。文字列の最大サイズはJava VMの実装により依存していますが、限定されています。リリース11.1以前は、oracle.xdb.dom.XDBNode.java
クラス内に含まれているノード値を管理するJava DOM APIは次のようになっていました。
public String getNodeValue (); public void setNodeValue (String value);
リリース11.1以前は、oracle.xdb.dom.XDBAttribute.java
クラス内に含まれている属性を管理するJava DOM APIは次のようになっていました。
public String getValue (); public void setValue (String value);
Oracle Database 11gリリース1 (11.1)から、パッケージoracle.xdb.dom
は非推奨になっています。このパッケージ内のJavaクラスXDBNode
およびXDBAttribute
は、パッケージoracle.xml.parser.v2
内でそれぞれクラスXMLNode
およびXMLAttr
に置き換えられています。また、これらのDOM APIはリリース11.1では拡張され、任意のサイズのテキスト・ノード値およびバイナリ・ノード値をサポートしています。
関連項目:
大規模ノードにおけるPL/SQLの使用方法の詳細は、「DBMS_XMLDOMを使用した大規模ノード処理」を参照してください。
非推奨のXDBNode
クラスおよびXDBAttribute
クラスの詳細は、「非推奨またはサポート外になったXMLTypeのクラスとメソッドのJava DOM API」を参照してください。
Java String
、Reader
、およびWriter
データはすべてUCS2で表現されます。これは、データベース・キャラクタ・セットと同じではない場合があります。また、ノード文字データはキャラクタ・セットIDでタグ付けされており、ノード値が移入するときに設定されます。
次に示すoracle.xml.parser.v2.XMLNode.java
のメソッドにより、サイズが64KBを超えるノードにアクセスできます。リーフ・ノード(属性、PI
、CDATA
など)ではないノードを取得または設定しようとすると、これらのAPIにより例外が発生します。また、その値を実際に書き込み、ノードへのストリーム・アクセス状態を維持する場合に使用するリソースを解放するclose()
を使用してください。
メソッドgetNodeValueAsBinaryStream()
およびgetNodeValueAsCharacterStream()
を使用して、取出しモードのパーサーによってDOMノードの値を取得できます。Oracle XML DBでは、パーサーによって書き込まれた入力ストリームからイベント・データを読み取ります。
バイナリ入力ストリームの場合:
public java.io.InputStream getNodeValueAsBinaryStream () throws java.io.IOException, DOMException;
メソッドgetNodeValueAsBinaryStream()
は、このクラスの定義メソッドを使用して読み取ることができるjava.io.InputStream
のインスタンスを戻します。ノードのデータ型はRAW
またはBLOB
である必要があります。それ以外の場合は、IOException
が発生します。次の例では、バイナリ50バイトのセグメントのノード値を読み取っています。
... oracle.xml.parser.v2.XMLNode node = null; ... java.io.InputStream value = node.getNodeValueAsBinaryStream (); // now read InputStream... byte buffer [] = new byte [50]; int returnValue = 0; while ((returnValue = value.read (buffer)) != -1) { // process next 50 bytes of node } ...
文字入力ストリームの場合:
public java.io.Reader getNodeValueAsCharacterStream() throws java.io.IOException, DOMException;
メソッドgetNodeValueAsCharacterStream()
は、このクラスの定義メソッドを使用して読み取ることができるjava.io.Reader
のインスタンスを戻します。ノードのデータ型が文字でもCLOB
でもない場合、まずノード・データは文字に変換されます。すべてのノード・データは最終的には文字形式になり、必要に応じてUCS2
に変換されます。次の例では、50文字のセグメントのノード値を読み取っています。
... oracle.xml.parser.v2.XMLNode node = null; ... java.io.Reader value = node.getNodeValueAsCharacterStream (); // now read InputStream char buffer [] = new char [50]; int returnValue = 0; while ((returnValue = value.read (buffer)) != -1) { // process next 50 characters of node } ...
このモデルでは、プッシュ・モードのパーサーを使用して、DOMノードの値を取得します。Oracle XML DBでは、パーサーによって読み取られた出力ストリームにノード・データを書き込みます。
バイナリ出力ストリームの場合:
public void getNodeValueAsBinaryStream (java.io.OutputStream pushValue) throws java.io.IOException, DOMException;
pushValue
で指定されるjava.io.OutputStream
の状態はopenである必要があります。ノードのデータ型はRAW
またはBLOB
である必要があります。それ以外の場合は、IOException
が発生します。ノード・バイナリ・データはOutputStream
のwrite()
メソッドを使用してpushValue
に書き込まれ、ノード値が完全にストリームに書き込まれるとclose()
メソッドがコールされます。
文字出力ストリームの場合:
public void getNodeValueAsCharacterStream (java.io.Writer pushValue) throws java.io.IOException, DOMException;
pushValue
で指定されるjava.io.Writer
の状態はopenである必要があります。ノードのデータ型が文字でもCLOB
でもない場合、まずデータは文字に変換されます。常に文字形式のノード・データは必要に応じてUCS2
に変換され、java.io.Writer
にプッシュされます。
このモデルでは、取出しモードのパーサーを使用して、DOMノードの値を設定します。Oracle XML DBでは、パーサーによって書き込まれた入力ストリームからイベント・データを読み取ります。
バイナリ入力ストリームの場合:
public void setNodeValueAsBinaryStream (java.io.InputStream pullValue) throws java.io.IOException, DOMException;
pullValue
で指定されるjava.io.InputStream
の状態はopenである必要があります。ノードのデータ型はRAW
またはBLOB
である必要があります。それ以外の場合は、IOException
が発生します。pullValue
のバイナリ・データ全体がInputStream
のread()
メソッドを使用して読み取られ、ノード値を置換します。
import java.io.InputStream; import oracle.xml.parser.*; ... oracle.xml.parser.v2.XMLNode node = null; ... byte [] buffer = new byte [500]; java.io.InputStream istream; //user-defined input stream node.setNodeValueAsBinaryStream (istream);
文字入力ストリームの場合:
public void setNodeValueAsCharacterStream (java.io.Reader pullValue) throws java.io.IOException, DOMException;
pullValue
で指定されるjava.io.Reader
の状態はopenである必要があります。ノードのデータ型が文字でもCLOB
でもない場合、文字データはUCS2
からノード・データ型に変換されます。ノードのデータ型が文字またはCLOB
の場合、pullValue
から読み取られた文字データは、UCS2
からノードのキャラクタ・セットに変換されます。
このモデルでは、プッシュ・モードのパーサーを使用して、DOMノードの値を設定します。Oracle XML DBでは、パーサーによって読み取られた出力ストリームにノード・データを書き込みます。
バイナリ出力ストリームの場合:
public java.io.OutputStream setNodeValueAsBinaryStream () throws java.io.IOException, DOMException;
メソッドsetNodeValueAsBinaryStream()
は、コール元によるノード値の書込み先となるjava.io.OutputStream
のインスタンスを戻します。ノードのデータ型はRAW
またはBLOB
である必要があります。それ以外の場合は、IOException
が発生します。次の例では、Oracle XML DBまたはOracle XML Developer's Kitが提供するjava.io.OutputStream
の実装に書き込むことで、ノード値をバイナリ・データに設定しています。
文字出力ストリームの場合:
public java.io.Writer setNodeValueAsCharacterStream () throws java.io.IOException, DOMException;
メソッドsetNodeValueAsCharacterStream()
は、コール元によるノード値の書込み先となるjava.io.Writer
のインスタンスを戻します。書き込まれた文字データはまず、必要に応じてUCS2
からノードのキャラクタ・セットに変換されます。ノードのデータ型が文字でもCLOB
でもない場合、文字データはノード・データ型に変換されます。同様に、次の例では、Oracle XML DBまたはOracle XML Developer's Kitが提供するjava.io.Writer
の実装に書き込むことで、ノード値を文字データに設定しています。
import java.io.Writer; import oracle.xml.parser.*; ... oracle.xml.parser.v2.XMLNode node = null; ... char [] buffer = new char [500]; java.io.Writer writer = node.setNodeValueAsCharacterStream (); for (int k = 0; k < 10; k++) { byte segment [] = new byte [50]; // copy next subset of buffer into segment writer.write (segment); } writer.flush (); writer.close();
関連項目:
『Oracle Database XML Java API Reference』
大規模ノードのためのC関数の詳細は、Oracle Database XML C APIリファレンスを参照してください。
Oracle XML DBはwriter
またはOutputStream
を作成し、それをノード値が完全に書き込まれるまで繰り返しwrite()
メソッドをコールするユーザーに渡します。新規ノード値は、ユーザーがclose()
メソッドをコールするときのみ反映されます。
Java DOM API for XMLおよびJava Database Connectivity (JDBC)を使用して、Oracle XML DBに対して、バイナリXMLとしてエンコードされたXMLデータを読書きできます。この処理には通常の読書きプロシージャが関与します。
XMLデータは、データ型XMLType
を使用してOracle XML DBに格納でき、この抽象データ型の記憶域モデルの1つが、XMLデータの簡潔なXML Schema対応のエンコーディングであるバイナリXMLです。バイナリXMLはデータベース内のXMLType
の記憶域モデルとして使用することができますが、データベース外にあるXMLデータに対しても使用することができます。XMLデータのクライアント側処理には、Oracle XML DB内に格納されているデータや、データベース外に存在する一時データが関わることがあります。
バイナリXMLはXML Schemaに対応しており、必要性とデータに応じて、各種のコード体系を使用することができます。このため、バイナリXMLデータを操作するためには、関連するXML Schemaとエンコーディングについて、データとこのメタデータの両方が必要です。
データベースに格納されているXMLType
データの場合、このメタデータもデータベースに格納されます。ただし、データベースとデータのセットアップに応じて、メタデータが適用されるデータと同一のサーバーにメタデータが格納されない場合があります。この場合、データベースに対してバイナリXMLデータを読書きするためには、次の手順を実行する必要があります。
メタデータのコンテキスト・インスタンスを作成します。
このコンテキストを、データベース内のバイナリXMLデータにアクセスするために使用するデータ接続に関連付けます。データ接続は、専用接続でも接続プールでもかまいません。クラスjava.sql.Connection
のメソッドgetDedicatedConn()
およびgetConnPool()
を使用して、それらの接続の型に応じて、これら2つの接続型へのハンドルを取得します。
すると、アプリケーションがデータ接続上でバイナリXMLデータをエンコードまたはデコードする必要がある場合、それに必要なメタデータが自動的にフェッチされます。一連の動作の全体は次のとおりです。
クラスjava.sql.Connection
にXMLデータ接続オブジェクトを作成します。
パッケージoracle.xml.binxml
内のメソッドBinXMLMetadataProviderFactory.createDBMetadataProvider()
を使用して、必要に応じて1つ以上のメタデータ・コンテキストを作成します。メタデータ・コンテキストは、メタデータ・リポジトリと呼ばれることもあります。メタデータ・コンテキストは、専用接続または接続プールから作成することができます。
メタデータ・コンテキストをバイナリXMLデータ接続に関連付けます。これには、パッケージoracle.xml.binxml
内のメソッドDBBinXMLMetadataProvider.associateDataConnection()
を使用します。
(オプション) XMLデータがデータベース外に由来するものの場合は、メソッドoracle.xdb.XMLType.setFormatPref()
を使用して、データベースに送信されるXMLデータがバイナリXML形式でエンコードされるように指定します。これは、DOM文書(クラスoracle.xdb.XMLType
)に適用されます。バイナリXMLを指定しない場合、データはテキストとしてデータベースに送信されます。
通常のJavaメソッドを使用して、データベースに対してXMLデータを読書きします。バイナリXML文書のエンコードやデコードに必要なときは常に、メタデータ・コンテキストを使用して、必要なメタデータが自動的にフェッチされます。
Java DOM API for XMLを使用して、クライアント・レベルのXMLデータに対して操作します。
例13-15に、これを示します。
関連項目:
『Oracle XML Developer's Kitプログラマーズ・ガイド』
例13-15 バイナリXMLでのJava DOM APIの使用
import java.sql.*; import oracle.jdbc.*; import oracle.jdbc.pool.OracleDataSource; import oracle.xdb.XMLType; import oracle.xml.binxml.*; class tdadxdbxdb11jav001 { public static void printBinXML() throws SQLException, BinXMLException { // Create datasource to connect to local database OracleDataSource ods = new OracleDataSource(); ods.setURL("jdbc:oracle:kprb"); System.out.println("Starting Binary XML Java Example"); // Create data connection Connection conn = ods.getConnection(); // Create binary XML metadata context, using connection pool DBBinXMLMetadataProvider repos = BinXMLMetadataProviderFactory.createDBMetadataProvider(); repos.setConnectionPool(ods); // Associate metadata context with data connection repos.associateDataConnection(conn); // Query XML data stored in XMLType column as binary XML Statement stmt = conn.createStatement(); ResultSet rset = stmt.executeQuery("SELECT doc FROM po_binxmltab"); // Get the XMLType object while (rset.next()) { XMLType xmlobj = (XMLType) rset.getObject(1); // Perform XMLType operation String xmlvalue = xmlobj.getStringVal(); System.out.println(xmlvalue); } // Close result set, statement, and connection rset.close(); stmt.close(); conn.close(); System.out.println("Completed Binary XML Java Example"); } }
脚注の凡例
脚注1:ここでは、XMLデータがXML Schemaに登録済であり、XMLType
の列に格納されていると想定しています。