この章では、Java Database Connectivity(JDBC)を介したXMLType
データのフェッチなど、JavaでXMLType
を使用する方法を説明します。
この章の内容は次のとおりです。
Oracle XML DBは、Javaドキュメント・オブジェクト・モデル(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リファレンス』 |
Java DOM API for XMLType
は、Oracle XML DBへの格納方法にかかわらず、すべての妥当なXML文書を処理します。XML文書は、XML Schemaに基づくか、XML Schemaに基づかないか(基礎となる記憶域モデルの形式が何であるか)にかかわらず、アプリケーションで同様に表示されます。Java DOM APIは、クライアントおよびサーバーの両方で動作します。
第12章「PL/SQL API for XMLType」で説明したとおり、Oracle XML DB DOM APIは、W3CのDOMレベル1.0およびレベル2.0のコア勧告に準拠しています。
Java DOM API for XMLType
を使用すると、別のキャラクタ・セットでエンコードされたデータからXMLType
インスタンスを作成できます。また、要求したキャラクタ・セットでXMLコンテンツを取り出すためのgetBLOBVal()
メソッドが提供されています。
Java DOM API for XMLType
を使用して、JavaアプリケーションからOracle XML DBリポジトリに格納されたXML文書にアクセスできます。ネーミングは、W3CのDOM勧告で指定されている、DOMへのJavaバインディングに準拠しています。リポジトリには、XML Schemaに基づくドキュメントおよび基づかないドキュメントの両方を含めることができます。
Oracle XML DB内のXML文書など、Oracle Database内のすべてのデータにアクセスするための、Javaアプリケーション用のSQLベースの方法です。oracle.xdb.XMLType
JavaクラスのcreateXML()
メソッドを使用します。
JDBCユーザーは、XMLType
表を問い合せて、SQL XMLType
データ型でサポートされるすべてのメソッドをサポートするJDBC XMLType
インタフェースを取得できます。Java(JDBC)API for XMLType
インタフェースは、DOMDocumentインタフェースを実装できます。
例14-1 XMLType Java: JDBCを使用したXMLType表の問合せ
次に、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.createXML(orset.getOPAQUE(1)); // get the XMLDocument as a string... Document podoc = (Document)poxml.getDOM(); }
SQLでgetCLOBVal()
、getStringVal()
またはgetBLOBVal(csid)
を使用し、Javaでoracle.sql.CLOB
、java.lang.String
またはoracle.sql.BLOB
として結果を取得します。次に、Javaのコード例を示します。
DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());
Connection conn =
DriverManager.getConnection("jdbc:oracle:oci8:@", "QUINE", "CURRY");
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
}
PreparedStatement
でgetOPAQUE()
メソッドをコールしてXMLType
インスタンス全体を取得し、XMLType
コンストラクタを使用して、そのインスタンスからoracle.xdb.XMLType
クラスを作成します。これによって、XMLType
クラスでJava関数を使用して、データにアクセスできます。
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.createXML(orset.getOPAQUE(1));
// get the XML as a string...
String poString = poxml.getStringVal();
例14-3 XMLType Java: XMLTypeデータを直接戻す方法
次の例では、getObject()
メソッドを使用してResultSet
からXMLType
を直接取得します。このコード例は、最も簡単にResultSet
から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();
}
例14-4 XMLType Java: XMLTypeデータを戻す方法
次の例では、XMLType
のOUT
変数をSQL文にバインドします。この出力パラメータは、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 extractValue(OBJECT_VALUE,'/PurchaseOrder/Reference') = 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
データを更新、挿入および削除することもできます。
CLOB
または文字列をINSERT
、UPDATE
またはDELETE
文にバインドし、SQL内でXMLType
コンストラクタを使用してXMLインスタンスを作成します。
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();
PreparedStatement
でsetObject()
またはsetOPAQUE()
を使用して、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();
例14-6 XMLType Java: XMLTypeでのメタデータの取得
XMLType
値を選択すると、JDBCによって、列がOPAQUE
型として記述されます。列型の名前を選択し、それをXMLTYPE
と比較すると、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 }
例14-7 XMLType Java: XMLType列の要素の更新
次の例では、XMLType
列に格納されているPurchaseOrder
内のdiscount
要素を更新します。この場合、Java Database Connectivity(JDBC)およびoracle.xdb.XMLType
クラスを使用します。この例では、Java(JDBC)を使用してXMLType
を挿入、更新または削除する方法も示します。パーサーを使用してメモリー内DOMツリーを更新し、更新されたXML値を列に書き込みます。
-- create po_xml_hist table to store old PurchaseOrders CREATE TABLE po_xml_hist ( xpo XMLType ); /* DESCRIPTION Example for oracle.xdb.XMLType NOTES 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 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 ---------------------- SELECT x.xpo.getCLOBVal() FROM po_xml x;
更新された発注書の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>
XMLType
表からのXMLType
インスタンスの選択
XPath式に基づくXMLType
インスタンスの一部の抽出
要素の有無の確認
XSLに基づく別のXML形式へのXMLType
インスタンスの変換
XML Schemaに対する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()){ 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); } } }
大規模なXML文書(通常4000文字を超える場合)がJDBCのString
オブジェクトを使用してXMLType
の表または列に挿入されると、次のランタイム・エラーが発生します。
"java.sql.SQLException: Data size bigger than max size for this type"
このエラーは、JavaのCLOB
オブジェクトを使用して大規模なXML文書を格納することで回避できます。例14-9に、大規模な文書をXMLType
列にロードする方法を示します。XMLType
表の場合も同じ方法を使用できます。CLOB
オブジェクトは、クライアント側でクラスoracle.sql.CLOB
を使用して作成されます。このクラスは、Oracle JDBC Driverによる標準JDBCインタフェースjava.sql.Clob
の実装です。
例14-9 大規模なXML文書のロード
この例では、XMLType
メソッドのinsertXML()
によって大規模なXML文書が、表poTable
のXMLType
の列purchaseOrder
に挿入されます。この処理には、XML文書が含まれるCLOB
オブジェクトが使用されます。CLOB
オブジェクトは、JDBCのプリコンパイルされたSQL文にバインドされます。この文によって、データがXMLType
列に挿入されます。
この例を実行するための前提条件は、次のとおりです。
Oracle Databaseがリリース9.2.0.1以上であること。
ターゲット・データベース表が存在すること。例を実行する前に、次のSQLを実行してください。
CREATE TABLE poTable (purchaseOrder XMLType);
XMLType
メソッドのinsertXML()
の仮パラメータは、次のとおりです。
xmlData
: XMLType
列に挿入するXMLデータ
conn
: データベース接続オブジェクト(Oracle Connection Object)
...
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 using the getCLOB method.
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();
}
}
insertXML()
メソッドはメソッドgetCLOB()
をコールして、XMLデータを格納するCLOB
オブジェクトを作成して戻します。getCLOB()
メソッドの仮パラメータは、次のとおりです。
xmlData
: XMLType
列に挿入するXMLデータ
conn
: データベース接続オブジェクト(Oracle Connection Object)
...
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に基づく文書の場合)
例14-10 Java DOM APIを使用したDOMオブジェクトの作成
次の例では、Java DOM API for XMLType
を使用してDOMオブジェクトを作成し、それをXML Schemaで指定された形式で格納します。この例では、XML Schemaに対する検証は示されていません。
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 XDK for Javaの相互作用を円滑にするOracle固有の拡張機能も提供します。Oracleの拡張機能のリストは、次のURLを参照してください。
http://www.oracle.com/technology/tech/xml/
XMLDocument
は、インスタンス化されたXML文書用のDOMを表すクラスです。XMLType
の値は、Document
の引数を取るXMLType
コンストラクタを使用してXML文書から取得できます。
XMLType createXML(Connection conn, Document domdoc)
表14-1に、Java DOM API for XMLType
のクラスおよび実装されるW3CのDOMインタフェースを示します。Java DOM APIクラスはすべて、oracle.xml.parser.v2
パッケージに入っています。
表14-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 |
XMLNodeList |
org.w3c.dom.NodeList |
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
: XMLNodeList
を使用
XDBNotation
: XMLNotation
を使用
XDBProcInst
: XMLPI
を使用
XDBText
: XMLText
を使用
図14-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;
このメソッドは、このクラスの定義メソッドを使用して読み取ることができる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;
このメソッドは、このクラスの定義メソッドを使用して読み取ることができる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;
このメソッドは、コール元によるノード値の書込み先となるjava.io.OutputStream
のインスタンスを戻します。ノードのデータ型はRAW
またはBLOB
である必要があります。それ以外の場合は、IOException
が発生します。次の例では、Oracle XML DBまたはOracle XDKが提供するjava.io.OutputStream
の実装に書き込むことで、ノード値をバイナリ・データに設定しています。
文字出力ストリームの場合:
public java.io.Writer setNodeValueAsCharacterStream () throws java.io.IOException, DOMException;
このメソッドは、コール元によるノード値の書込み先となるjava.io.Writer
のインスタンスを戻します。書き込まれた文字データはまず、必要に応じてUCS2
からノードのキャラクタ・セットに変換されます。ノードのデータ型が文字でもCLOB
でもない場合、文字データはノード・データ型に変換されます。同様に、次の例では、Oracle XML DBまたはOracle XDKが提供する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を指定しない場合、データはテキスト(CLOB
)として格納されます。
通常のJavaメソッドを使用して、データベースに対してXMLデータを読書きします。バイナリXML文書のエンコードやデコードに必要なときは常に、メタデータ・コンテキストを使用して、必要なメタデータが自動的にフェッチされます。
Java DOM API for XMLを使用して、クライアント・レベルのXMLデータに対して操作します。
例14-11に、これを示します。
例14-11 バイナリ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
の列に格納されていると想定しています。