この章では、Java Database Connectivity(JDBC)を介したXMLType
データのフェッチなど、JavaでXMLType
を使用する方法を説明します。
この章の内容は次のとおりです。
Oracle XML DBはJava Document Object Model (DOM) Application Program Interface (API) for XMLType
をサポートします。これはXML Schemaに基づく文書とXML Schemaに基づかない文書に対する、クライアントおよびサーバー用の汎用APIです。このAPIは、Javaパッケージoracle.xml.parser.v2
を使用して実装されます。DOMは、XML文書のメモリー内ツリーベースのオブジェクト表現で、要素および属性へのプログラム・アクセスを可能にします。DOMオブジェクトおよびインタフェースは、W3C勧告の一部です。DOMは、解析対象ドキュメントをオブジェクトのツリーとして表示します。
JDBCを使用してXMLType
データにアクセスするには、クラスoracle.xdb.XMLType
を使用します。
どのXML Schemaにも準拠しないXML文書には、すべての妥当なXML文書を処理可能なJava DOM API for XMLType
を使用できます。
関連項目: 『Oracle Database XML Java API Reference』 |
Java DOM API for XMLType
は、Oracle XML DBへの格納方法にかかわらず、すべての種類の妥当なXML文書を処理します。XML文書は、XML Schemaに基づくか、XML Schemaに基づかないか(基礎となる記憶域モデルの形式が何であるか)にかかわらず、アプリケーションで同様に表示されます。Java DOM APIは、クライアントおよびサーバーの両方で動作します。
第13章「PL/SQL API for XMLType」で説明したとおり、Oracle XML DB DOM APIは、W3CのDOMレベル1.0およびレベル2.0のコア勧告に準拠しています。
Java DOM API for XMLType
を使用すると、別のキャラクタ・セットでエンコードされたデータからXMLType
インスタンスを作成できます。
Java DOM API for XMLType
を使用して、JavaアプリケーションからOracle XML DBリポジトリに格納されたXML文書にアクセスできます。ネーミングは、W3CのDOM勧告で指定されている、DOMへのJavaバインディングに準拠しています。リポジトリには、XML Schemaに基づくドキュメントおよび基づかないドキュメントの両方を含めることができます。
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リリース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インタフェースを実装できます。
例15-1に、JDBCを使用してXMLType
表を問い合せる方法を示します。
例15-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();
}
次のいずれかの方法で、JDBCを使用してXMLType
データを選択できます。
SQLでSQL/XML関数XMLSerialize
を使用し、Javaでoracle.sql.CLOB
、java.lang.String
またはoracle.sql.BLOB
として結果を取得します。例15-2のJavaスニペットに、これを示します。
PreparedStatement
でメソッドgetObject()
をコールして、XMLType
インスタンス全体を取得します。このメソッドの戻り値は、oracle.xdb.XMLType
型です。これによって、XMLType
クラスでJava関数を使用して、データにアクセスできます。この方法を例15-3に示します。
例15-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 }
例15-3では、getObject()
メソッドを使用してResultSet
からXMLType
インスタンスを直接取得します。
例15-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();
}
例15-4では、XMLType
型の出力パラメータをSQL文にバインドします。この出力パラメータは、XMLType
データ型として登録されます。
例15-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; } }
Java Database Connectivity(JDBC)を使用して、XMLType
データを更新、挿入および削除することもできます。
XMLType
データを次のいずれかの方法で、更新、挿入または削除できます。
CLOB
または文字列をINSERT
、UPDATE
またはDELETE
文にバインドし、SQL内でXMLType
コンストラクタを使用してXMLインスタンスを作成します。例15-5に、これを示します。
PreparedStatement
でsetObject()
を使用して、XMLType
インスタンス全体を設定します。例15-6に、これを示します。
例15-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();
例15-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();
XMLType
値を選択すると、JDBCによって、列が不透明型として記述されます。列型の名前を選択し、それをXMLTYPE
と比較すると、XMLType
インスタンスを処理しているかどうかを確認できます。例15-7に、これを示します。
例15-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 }
例15-8では、XMLType
列に格納されているPurchaseOrder
要素内のdiscount
要素を更新します。ここではJDBCおよびoracle.xdb.XMLType
クラスを使用します。XMLパーサーを使用してDOMツリーを更新し、更新されたXML値をXMLType
列に書き込みます。
例15-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;
例15-9は、例15-8から得られる更新済の発注書を示します。
例15-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>
例15-10では、次のものがすべて処理されます。
XMLType
表からのXMLType
インスタンスの選択
XPath式に基づくXMLType
インスタンスの一部の抽出
要素の有無の確認
XSLに基づく別のXML形式へのXMLType
インスタンスの変換
XML Schemaに対するXMLType
文書の妥当性の確認
例15-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)); } Java DOM API for XMLType Beta Draft Java DOM API for XMLType 15-11 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); } } }
大規模なXML文書(通常4000文字を超える場合)がJDBCのString
オブジェクトを使用してXMLType
の表または列に挿入されると、次のランタイム・エラーが発生します。
"java.sql.SQLException: Data size bigger than max size for this type"
このエラーは、JavaのCLOB
オブジェクトを使用して大規模なXML文書を保持することで回避できます。例15-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)
例15-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(); } }
JavaメソッドinsertXML()
は、メソッドgetCLOB()
をコールして、XMLデータを格納するCLOB
オブジェクトを作成して戻します。getCLOB()
メソッドの仮パラメータは例15-12で定義され、次のとおりです。
xmlData
: XMLType
列に挿入するXMLデータ
conn
: データベース接続オブジェクト(Oracle Connection Object)
例15-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;
}
関連項目: 『Oracle Database SecureFilesおよびラージ・オブジェクト開発者ガイド』 |
Java DOM APIを使用してOracle XML DBからXMLデータを取得する場合:
接続がThinの場合は、XML
Document
インスタンスを取得します。
接続がThickまたはkprbの場合は、getDOM()
メソッドでXDB
Document
インスタンスを、getDocument()
メソッドでXML
Document
インスタンスを取得します。getDOM()
メソッドとXDBDocument
クラスは非推奨になりました。
XMLDocument
およびXDBDocument
(非推奨)は、どちらもW3Cドキュメント・オブジェクト・モデル(DOM)・インタフェースのインスタンスです。このドキュメント・インタフェースからドキュメントの要素にアクセスすると、W3CのDOM勧告に指定されたすべての操作を実行できます。DOMは、次のものに対して機能します。
XML Schemaに基づく、基づかないに関係なく、あらゆる種類のXML文書
文書で使用されるすべての形式の基礎となる記憶域
キャラクタ・ラージ・オブジェクト(Character Large Object: CLOB)
バイナリ・ラージ・オブジェクト(Binary Large Object: BLOB)
オブジェクト・リレーショナル
Java DOM API for XMLType
は、XMLオブジェクトの子およびプロパティ(名前、名前空間など)を取得するために、文書内でのディープ検索およびシャロウ検索をサポートします。Java DOM API for XMLType
はDOM 2.0勧告に準拠し、名前空間を認識します。
Java API for XMLType
を使用すると、アプリケーションではプログラムによって、その場で(動的に)XML文書を作成できます。そのような文書は、登録されたXML Schemaに準拠することもあれば、しないこともあります。
XML Schemaに基づく文書を作成するには、Java DOM API for XMLType
の拡張機能を使用して、使用するXML Schema URLを指定します。XML Schemaに基づく文書では、作成中のDOMが指定されたXML Schemaに準拠するかどうか(適切な子が適切な文書に挿入されているか)を検証します。
注意: Java DOM API forXMLType は型および制約のチェックは実行しません。 |
DOMオブジェクトの作成後は、Oracle XML DB Resource API for Javaを使用して、DOMオブジェクトをOracle XML DBリポジトリに保存できます。XML文書は次の適切な形式で格納されます。
BLOBインスタンス(スキーマに基づかない文書の場合)
XML Schemaで指定された形式(XML Schemaに基づく文書の場合)
例15-13では、Java DOM API for XMLType
を使用してDOMオブジェクトを作成し、関連するXML Schemaで指定された形式で格納します。この例では、XML Schemaに対する検証は示されていません。
例15-13 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();
Oracle XML DBは、W3CのDOMレベル2勧告をサポートします。W3C勧告に加えて、Oracle XML DB DOM APIは、アプリケーションとOracle XML Developer's Kit for Javaの相互作用を円滑にするOracle固有の拡張機能も提供します。Oracleの拡張機能のリストは、次のURLを参照してください。
http://www.oracle.com/technetwork/database-features/xmldb/overview/index.html
XMLDocument
は、インスタンス化されたXML文書用のDOMを表すクラスです。XMLType
の値は、Document
の引数を取るXMLType
コンストラクタを使用してXML文書から取得できます。
XMLType createXML(Connection conn, Document domdoc)
表15-1に、Java DOM API for XMLType
のクラスおよび実装されるW3CのDOMインタフェースを示します。Java DOM APIクラスはすべて、oracle.xml.parser.v2
パッケージに入っています。
表15-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 |
リリース2(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
を使用
図15-1に、Java DOM API for XMLType
を示します脚注1 。次の手順を実行します。
XMLType
表または表のXMLType
列からXMLデータを取り出します。XMLデータをフェッチすると、OracleによってXMLType
のインスタンスが作成されます。これによって、getDocument()
メソッドを使用して文書のインスタンスを取得できます。その後、Java DOM API for XMLType
を使用してDOMツリーの要素を操作できます。
Java DOM API for XMLType
を使用してDOMツリーの要素を操作します。変更されたデータはXMLTypeインスタンスに格納されますが、データはJDBC更新を使用して戻されます。
XMLType
およびXMLDocument
インスタンスは、各クラスでclose()
メソッドを使用してクローズする必要があります。クローズすると、保持されていた基礎となるメモリーがすべて解放されます。
Oracle Database 11gリリース1 (11.1)以前は、ノードのサイズが64KB未満に制限されていました。ノード値を設定および取得するJavaメソッドはjava.lang.String
型の引数のみでサポートされているためです。文字列の最大サイズはJava VMの実装により依存していますが、限定されています。リリース11.1以前は、oracle.xdb.dom.XDBNode.java
クラス内に含まれているノード値を管理するJava DOM APIは次のようになっていました。
public String getNodeValue (); public void setNodeValue (String value);
以前は、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では拡張され、任意のサイズのテキスト・ノード値およびバイナリ・ノード値をサポートしています。
注意: 大規模ノード機能は、Thickまたはkprb接続でのみ動作します。Thin接続では動作しません。 |
関連項目:
|
Java String
、Reader
、およびWriter
データはすべてUCS2
で表現されます。これは、データベース・キャラクタ・セットと同じではない場合があります。また、ノード文字データはキャラクタ・セットIDでタグ付けされており、ノード値が移入するときに設定されます。
次に示すoracle.xml.parser.v2.XMLNode.java
のメソッドにより、サイズが64KBを超えるノードにアクセスできます。リーフ・ノード(属性、PI
、CDATA
など)ではないノードを取得または設定しようとすると、これらのAPIにより例外が発生します。また、その値を実際に書き込み、ノードへのストリーム・アクセス状態を維持する場合に使用するリソースを解放するclose()
を使用してください。
バイナリ入力ストリームの場合:
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 } ...
バイナリ出力ストリームの場合:
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
にプッシュされます。
バイナリ入力ストリームの場合:
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
からノードのキャラクタ・セットに変換されます。
バイナリ出力ストリームの場合:
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 XML DBはwriter
またはOutputStream
を作成し、それをノード値が完全に書き込まれるまで繰り返しwrite()
メソッドをコールするユーザーに渡します。新規ノード値は、ユーザーがclose()
メソッドをコールするときのみ反映されます。
XMLデータはXMLType
を使用してOracle XML DBに格納でき、この抽象データ型の記憶域モデルの1つはバイナリXMLです。バイナリXMLはXMLデータの簡潔な、XML Schema対応のエンコーディングです。データベース内のXMLType
の記憶域モデルとして使用することができますが、データベース外にあるXMLデータに対しても使用することができます。XMLデータのクライアント側処理には、Oracle XML DB内に格納されているデータや、データベース外に存在する一時データが関わることがあります。
Java DOM APIを使用して、Oracle XML DBに対して、バイナリXML形式でエンコードされたXMLデータを読書きすることができます。この処理には通常の読書きプロシージャが関与します。
バイナリ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データに対して操作します。
例15-14に、これを示します。
例15-14 バイナリ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
の列に格納されていると想定しています。