この章では、Extensible Markup Language (XML) Parsing for Javaについて説明します。
内容は次のとおりです。
内容は次のとおりです。
Oracle XML ParserはXML文書を読み取り、Document Object Model (DOM)アプリケーション・プログラミング・インタフェース(API)またはSimple API for XML (SAX)を使用してそのコンテンツと構造にアクセスします。解析は検証モードまたは非検証モードで行えます。
この章では、次のテクノロジを十分に理解していると想定します。
Document Object Model (DOM): XML文書の構造を示すメモリー内ツリー表現です。
Simple API for XML (SAX): イベントベースのXML解析の標準です。
Java API for XML Processing (JAXP): JavaアプリケーションでXMLを処理するための標準インタフェースで、DOM標準とSAX標準をサポートします。
Document Type Definition (DTD): XML文書の有効な構造を定義する一連のルールです。
XML Schema: XML文書の有効なデータ型の構造を定義するWorld Wide Web Consortium (W3C)勧告です。
XML名前空間: XML文書内の要素名や属性名を区別するためのメカニズムです。
バイナリXML: コンパクトなスキーマを認識した形式を使用するXML表現。拡張性のあるDOMも拡張性のないDOMも、この形式でXML文書を保存できます。
詳細は、「関連ドキュメント」のXMLの資料のリストを参照してください。
DOMレベル1、レベル2およびレベル3の仕様はW3C勧告です。その仕様へのリンクについては、次を参照してください。
http://www.w3.org/DOM/DOMTR
SAXにはバージョン1.0(非推奨)と2.0があります。SAXはW3C仕様ではありません。SAXのドキュメントについては、次を参照してください。
http://www.saxproject.org/
XML名前空間はW3C勧告です。仕様については、次を参照してください。
http://www.w3.org/TR/REC-xml-names
JCR 1.0(JSR 170とも呼ばれます)は、アプリケーションがコンテンツ・リポジトリと対話するための標準Java APIを定義しています。
関連項目:
『Oracle XML DB開発者ガイド』
JAXPは、プロセッサの実装に関係なくDOM、SAX、XML SchemaおよびExtensible Stylesheet Language Transformation (XSLT)を使用可能にする標準APIです。JAXPの仕様およびその他の情報については、次を参照してください。
http://www.oracle.com/technetwork/java/index.html
関連項目:
Oracle XML Developer's Kit (XDK)でサポートする標準の詳細は、「Oracle XML Developer's Kit標準」を参照してください
XMLノードへのDOMストリーム・アクセスはProcedural Language/Structured Query Language (PL/SQL)およびJava APIによって行われます。XML文書内のノードは64KBを大幅に超えることができるようになりました。したがって、Joint Photographic Experts Group (JPEG)、Word、PDF、リッチ・テキスト形式(RTF)およびHTML文書を問題なく格納できます。
関連項目:
Javaの巨大ノードに関する機能の詳細は、『Oracle XML DB Developer's Guide』を参照してください。
XMLParser
は、XML Parser for Javaの抽象ベース・クラスです。インスタンス化されたパーサーは、parse()
メソッドを起動してXML文書を読み取ります。
XMLDOMImplementation
ファクトリ・メソッドは、バイナリXMLを解析し、拡張性のあるDOMを作成する別の方法を提供します。
図4-1に、XMLParser
を使用した解析の基本プロセスを示します。図はXMLDOMImplementation()
には適用されません。
Javaアプリケーションでは、次のAPIを使用して、解析済XML文書にアクセスできます。
DOM API
DOM APIは、XML文書を解析し、メモリー内に文書のツリー表現を構築します。DOM APIを使用して解析するには、DOMParser
オブジェクトまたはXMLDOMImplementation
インタフェース・ファクトリ・メソッドを使用してプラガブルで拡張性のあるDOM (SDOM)を作成します。
SAX API
SAX APIは、XML文書をイベントのストリームとして処理します。したがって、プログラムから文書内のランダムな位置へのアクセスはできません。SAX APIを使用して解析するには、SAXParser
オブジェクトを使用します。
JAXP
JAXPは、DOM、SAXおよびExtensible Stylesheet Language (XSL)をサポートするJava固有のAPIです。JAXPを使用して解析するには、DocumentBuilder
またはSAXParser
オブジェクトを使用します。
後続のトピックでは、例4-1のサンプルXML文書を使用して、DOM、SAX、JAXPの違いを示します。
例4-1 サンプルXML文書
<?xml version="1.0"?> <EMPLIST> <EMP> <ENAME>MARY</ENAME> </EMP> <EMP> <ENAME>SCOTT</ENAME> </EMP> </EMPLIST>
DOM APIは、XML文書のインメモリー・ツリー表現を構築します。たとえば、例4-1に示した文書の場合、DOM APIは図4-2に示すインメモリー・ツリーを作成します。DOM APIは、ツリーをナビゲートおよび処理するためのクラスおよびメソッドを提供します。
DOM APIについて重要な点は次のとおりです。
DOM APIでは、オブジェクトがよく知られたツリー構造で提供されるため、SAX APIよりも簡単に使用できます。
ツリーは操作可能です。たとえば、要素を並べ替えたり、名前を変更できます。また、要素、属性とも追加および削除できます。
対話型アプリケーションでメモリー内にツリーを格納できるため、ユーザーがツリーにアクセスして操作できます。
XDKには、XPathをサポートするDOM API拡張が含まれています。(DOM標準ではXPathをサポートしませんが、ほとんどのXPath実装でDOMが使用されます。)
XDKではSDOMがサポートされます。詳細は、「SDOM」を参照してください。
XDKではプラガブルで拡張性のあるDOM (SDOM)がサポートされます。このサポートにより、メモリーの非効率、限定的なスケーラビリティ、DOM構成の制御不足という問題が緩和されます。
SDOMの作成および構成は主にXMLDOMImplementation
クラスを使用してサポートされます。
SDOMについて重要な点は次のとおりです。
SDOMでは、既存の形式のプラグイン外部XMLを使用できます。
プラグインXMLデータは、バイナリXML、XMLType
およびサード・パーティ製のDOMなど様々な形式が可能です。SDOMは外部XMLを内部表現にレプリケートする必要がありません。SDOMは、Reader
およびInfosetWriter
抽象インタフェースを介してプラグインXMLデータの上位で作成されます。
SDOMは一時ノードを持ちます。
ノードはアクセスされる場合にのみ作成され、使用されない場合は解放されます。
SDOMは、入力および出力ともにバイナリXMLを使用できます。
SDOMは、次の2つの方法でデータと対話します。
抽象InfosetReader
およびInfosetWriter
インタフェースを介して対話。
BinXML
データの読取りおよび書込みを行う場合、ユーザーはInfosetReader
およびInfosetWriter
のBinXML
実装を使用できます。他の形式のXML infosetの読取りおよび書込みを行う場合、ユーザーは独自の実装を使用できます。
BinXMLStream
に対するInfosetReader
およびInfosetWriter
アダプタの実装を介して対話。
関連項目:
XDK SDOMサポートは、次の要素で構成されます。
プラガブルなDOMでは、データ・レイヤーからDOM APIを分割できます。DOM APIは、InfosetReader
およびInfosetWriter
インタフェースによってデータから分離されます。
プラガブルなDOMを使用すると、1つのプロセッサから別のプロセッサへのXMLデータの移動が容易になります。
DOM APIには、データの上位に統合された標準APIが含まれており、ノード・アクセス、ナビゲーション、更新プロセスおよび検索機能がサポートされています。
関連項目:
遅延マテリアライズを使用すると、XDKはアクセスするノードのみを作成し、使用しないノードをメモリーから解放します。スケーラビリティが向上するため、非常に大きなXML文書も処理可能です。
関連項目:
DOM構成は他のアプリケーションに適合するように構成されています。DOMの構成には、読取り専用、ストリーム、一時更新およびシャドウ・コピーなど様々なアクセス・パターンを使用して、最大限のメモリーを使用および実行可能にできます。
関連項目:
Oracleで開発されたFast Infosetは、XML Infosetを表現するコンパクトなバイナリXML形式です。この形式は、国際標準ITU-T SG 17およびISO/IEC JTC1 SC6になっています。XML InfosetのFast Infoset表現は、Java XMLおよびWebサービス・コミュニティ内で一般的になっています。
Fast Infosetには、他の形式と比較して次のような利点があります。
XMLテキストと比較してよりコンパクトで、より高速な解析、より適切な直列化が可能です。
XMLテキストの解析よりも高速なエンコードおよびデコードが可能で、Fast Infosetドキュメントは一般に、対応するXMLテキストよりも20から60%小さくなります。
他のバイナリXML形式よりもパフォーマンスと圧縮率に勝っており、小規模ドキュメントから大規模ドキュメントまでバランスよく処理できます。
SDOMは、拡張性をサポートするXDK DOM構成です。直列化されたバイナリ・データの最上位に構築され、XPathやXSLTなどのアプリケーションにDOM APIを提供します。SDOMには、抽象的なAPI InfosetReaderを介してバイナリ・データを読み込む、オープンなプラグイン・アーキテクチャがあります。InfosetReader APIにより、SDOMは転送されるバイナリ・データをデコードし、ノードの開始場所を記憶し、デコードする場所を検索できます。このサポートにより、SDOMは使用されていないノードを解放し、必要なときにこれらのノードをバイナリ・データから再作成できます。バイナリ・データをファイルやBLOBなどの外部に保存すると、SDOMの拡張性が高まります。
JAXPを使用すると、SAXまたはDOMパーサーの実装をプラグインできます。XDKで提供されているSAX APIとDOM APIは、JAXPがサポートするベンダー固有実装の例です。
JAXPの主な利点は、相互運用可能なアプリケーションを作成できることです。JAXPを介して使用可能な機能を使用するアプリケーションでは、非常に簡単に実装を切り替えることができます。
JAXPの主な短所は、ベンダー固有のAPIよりも実行速度が遅いことです。また、JAXPには、Oracle固有のAPIが提供するいくつかの機能がありません。一部のOracle固有の機能はJAXP拡張メカニズムを介して使用できますが、これらの拡張を使用するアプリケーションは実装の切替えという柔軟性を失います。
名前空間は、XML文書内にある要素タイプ間または属性間の名前の競合を回避するメカニズムです。
例4-2は、会社の住所と従業員の住所の両方に<address>
タグを使用するXML文書です。XMLプロセッサは、会社の住所と従業員の住所を区別できません。
例4-3は、次の名前空間を使用して会社と従業員の<address>
タグを区別するXML文書です。
http://www.oracle.com/employee http://www.oracle.com/company
例4-3では、com
接頭辞を最初の名前空間に関連付け、emp
接頭辞を2番目の名前空間に関連付けています。
名前空間を使用した文書を解析する場合、次の用語を覚えておくと有用です。
名前空間URIは、xmlns
に割り当てられるURIです。例4-3では、http://www.oracle.com/employee
およびhttp://www.oracle.com/company
が名前空間URIです。
名前空間の接頭辞は、xmlns
で宣言された名前空間の識別子です。例4-3では、emp
およびcom
が名前空間の接頭辞です。
ローカル名は、名前空間の接頭辞が付いていない要素または属性の名前です。例4-3では、employee
およびcompany
がローカル名です。
修飾名は、ローカル名に接頭辞を加えたものです。例4-3では、emp:employee
およびcom:company
が修飾名です。
拡張名は、名前空間の接頭辞を名前空間URIで置換した結果です。例4-3では、http://www.oracle.com/employee:employee
およびhttp://www.oracle.com/company:company
が拡張要素名です。
例4-2 名前空間を使用しないサンプルXML文書
<?xml version='1.0'?> <addresslist> <company> <address>500 Oracle Parkway, Redwood Shores, CA 94065 </address> </company> <!-- ... --> <employee> <lastname>King</lastname> <address>3290 W Big Beaver Troy, MI 48084 </address> </employee> <!-- ... --> </addresslist>
例4-3 名前空間を使用したサンプルXML文書
<?xml version='1.0'?> <addresslist> <!-- ... --> <com:company xmlns:com="http://www.oracle.com/company"> <com:address>500 Oracle Parkway, Redwood Shores, CA 94065 </com:address> </com:company> <!-- ... --> <emp:employee xmlns:emp="http://www.oracle.com/employee"> <emp:lastname>King</emp:lastname> <emp:address>3290 W Big Beaver Troy, MI 48084 </emp:address> </emp:employee>
XML文書を解析するには、parse()
メソッドを起動します。通常、parse()
メソッドに伴って初期化メソッドおよび終了メソッドを起動します。
解析モードは検証または非検証のいずれかです。検証モードでは、解析によって文書が指定されたDTDまたはXMLスキーマに準拠しているかどうかが確認されます。非検証モードでは、パーサーは整形式であるかどうかのみ確認します。解析モードを設定するには、oracle.xml.parser.v2.XMLParser
に定義されているsetValidationMode()
メソッドを起動します。
表4-1に、XDKパーサーで使用できるsetValidationMode()
のフラグを示します。
表4-1 XML Parser for Javaの検証モード
名前 | 値 | XML Parserによる処理 . . |
---|---|---|
非検証モード |
|
XMLが整形式であることを確認し、データを解析します。 |
DTD検証モード |
|
XMLが整形式であることを確認し、XMLデータがDTDに対して妥当であるかどうかを検証します。 |
スキーマ検証モード |
|
XML文書を、その文書に対して指定されたXMLスキーマに従って検証します。 |
LAX検証モード |
|
スキーマ定義が検出されない場合、インスタンス・ドキュメントの一部またはすべての検証を試行します。定義が検出されない場合も、エラーは発生しません。 |
厳密な検証モード |
|
インスタンス・ドキュメント全体の検証を試行します。スキーマ定義が検出されない場合またはインスタンスが定義に準拠しない場合は、エラーが発生します。 |
部分検証モード |
|
DTD(存在する場合)に従って、入力XML文書のすべてまたは一部を検証します。DTDが存在しない場合、パーサーは非検証モードに設定されます。 |
自動検証モード |
|
DTDまたはXMLスキーマ(存在する場合)に従って、入力XML文書のすべてまたは一部を検証します。DTDとXMLスキーマのいずれも存在しない場合、パーサーは非検証モードに設定されます。 |
setValidationMode()
での検証モードの設定に加えて、oracle.xml.parser.schema.XSDBuilder
クラスを使用してXMLスキーマを構築し、XMLParser.setXMLSchema()
メソッドを起動することにより、このXMLスキーマを使用するようにパーサーを構成できます。この場合、XMLパーサーは検証モードを自動的にSCHEMA_STRICT_VALIDATION
に設定し、schemaLocation
およびnoNamespaceSchemaLocation
属性を無視します。検証モードをSCHEMA_LAX_VALIDATION
に変更することもできます。XMLParser.setDoctype()
メソッドは、DTDのパラレル・メソッドですが、setXMLSchema()
とは異なり、検証モードを変更しません。
関連項目:
検証の詳細は、「XML Schema Processor for Javaの使用」を参照してください
XMLParser
クラスおよびXSDBuilder
クラスの詳細は、Oracle Database XML Java APIリファレンスを参照してください
XML Parserに実装されているXML Compressorを使用して、XML文書を圧縮および解凍できます。圧縮アルゴリズムは、XMLタグのトークン化に基づいています。これは、すべてのXML文書にはタグの繰返しがあるため、それらのタグをトークン化すると、データが大幅に圧縮されることを前提としています。圧縮の程度は、文書のタイプに依存します。タグの数が多く、テキスト・コンテンツが少ないほど、圧縮率が向上します。
Oracle XML Parserは、XML文書から生成されたインメモリーDOMツリーまたはSAXイベントから、圧縮したバイナリ出力を生成します。表4-2に、2種類の圧縮を示します。
表4-2 DOMとSAXでのXML圧縮
タイプ | 説明 | 圧縮API |
---|---|---|
DOMベース |
目的は、DOMツリーの構造情報および階層情報を失うことなく、XML文書のサイズを小さくすることです。パーサーでは、解析済XML文書に対応するインメモリーDOMツリーがシリアライズされ、圧縮したXML出力ストリームが生成されます。シリアライズされたストリームは、再度読み取られると、DOMツリーを再生成します。 |
|
SAXベース |
SAXパーサーでは、XMLファイルを解析する際に圧縮したストリームが生成されます。SAXパーサーによって生成されたSAXイベントは、SAX圧縮ユーティリティによって処理されます。SAX圧縮ユーティリティは、圧縮したバイナリ・ストリームを生成します。 |
圧縮したXMLを生成するには、出力ストリームをコンストラクタに渡すことにより、 注意: |
DOMおよびSAXから生成された圧縮ストリームには互換性があるため、SAXから生成された圧縮ストリームを使用してDOMツリーを生成したり、その逆を行えます。通常、XML文書と同様に、圧縮したXMLデータ出力はデータベースにBLOB
データ・アイテムとして格納できます。
プログラムで大きなXML文書を解析し、メモリー内にDOMツリーを作成すると、パフォーマンスに影響する場合があります。DOMツリーをシリアライズすることにより、XML文書をバイナリ・ストリームに圧縮できます。圧縮したストリーム内のXMLデータを検証せずに、DOMツリーを再生成できます。圧縮したストリームはシリアライズされたストリームとして処理できますが、ストリーム内のデータは、Javaのデフォルトのシリアライズによって実装される圧縮よりも厳密に制御および管理されます。
注意:
Oracle Textは、圧縮されたXML文書を検索できません。解凍によりパフォーマンスが低下します。クライアントとサーバーの間でファイルを転送する場合、Hypertext Transfer Protocol (HTTP)圧縮が簡単です。
XML開発の基本コンポーネントはXML Parsingです。XML Parsing for JavaはスタンドアロンのXMLコンポーネントであり、プログラムで処理できるように、XML文書(場合によってはスタンドアロンのDTDまたはXMLスキーマも)を解析します。
内容は次のとおりです。
注意:
サポートされている任意のJava仮想マシン(JVM)のパーサーを使用できます。Oracle9i以降では、パーサーをデータベースにロードし、内部Oracle JVMを使用できます。その他のデータベース・バージョンでは、外部JVM内でパーサーを実行し、JDBCを介してデータベースに接続します。
図4-3に、標準的なXML処理アプリケーションでXMLパーサーを使用する方法を示します。
図4-3に示したアプリケーションの基本プロセスは次のとおりです。
DOMまたはSAXパーサーにより、入力XML文書が解析されます。たとえば、プログラムはXMLデータ文書、DTD、XMLスキーマおよびXSLスタイルシートを解析できます。
検証パーサーを実装すると、プロセッサは、提供されているDTDまたはXMLスキーマに対してXMLデータ文書が妥当であるかどうかの検証を試行します。
関連項目:
検証の詳細は、「XML Schema Processor for Javaの使用」を参照してください
XMLパーサーのクラスとメソッドについては、Oracle Database XML Java APIリファレンスを参照してください
XML Parser for Javaのデモ・プログラムは、$ORACLE_HOME/xdk/demo/java/parser
にあります。表4-3に、デモ・プログラムが格納されているサブディレクトリを示します。
表4-3 Javaパーサーのデモ
ディレクトリ | 内容 | プログラムの説明 |
---|---|---|
|
class.xml DemoUtil.java empl.xml family.dtd family.xml iden.xsl NSExample.xml traversal.xml |
XMLパーサーで一般的に使用するXMLファイルおよびJavaプログラムです。たとえば、XSLTスタイルシート |
|
DOMCompression.java DOMDeCompression.java SAXCompression.java SAXDeCompression.java SampleSAXHandler.java sample.xml xml.ser |
次のようなDOMおよびSAX圧縮が示されます。
|
|
AutoDetectEncoding.java DOM2Namespace.java DOMNamespace.java DOMRangeSample.java DOMSample.java EventSample.java I18nSafeXMLFileWritingSample.java NodeIteratorSample.java ParseXMLFromString.java TreeWalkerSample.java |
次のようなDOM APIの使用方法が示されます。
|
|
JAXPExamples.java age.xsl general.xml jaxpone.xml jaxpone.xsl jaxpthree.xsl jaxptwo.xsl oraContentHandler.java |
JAXPの様々な使用方法が示されます。
|
|
SAX2Namespace.java SAXNamespace.java SAXSample.java Tokenizer.java |
SAX APIの様々な使用方法が示されます。
|
|
XSLSample.java XSLSample2.java match.xml match.xsl math.xml math.xsl number.xml number.xsl position.xml position.xsl reverse.xml reverse.xsl string.xml string.xsl style.txt variable.xml variable.xsl |
XSLTを使用した文書の変換が示されます。
関連項目: 「XSLTプロセッサのデモ・プログラムの実行」 |
サンプル・プログラムのコンパイルおよび実行方法に関するドキュメントは、READMEファイルにあります。基本的な手順は次のとおりです。
$ORACLE_HOME/bin
(UNIXの場合)または%ORACLE_HOME%\bin
(Windowsの場合) にあるoraxml
ユーティリティは、XML文書を解析するコマンドライン・インタフェースです。XML文書が整形式であるか、および妥当であるかを確認します。
oraxml
を使用する場合、次の点を確認してください。
「XDK for Java環境の設定」の説明に従ってCLASSPATH
を設定し、CLASSPATH
環境変数がxmlparserv2.jar
ファイルを参照しています。
PATH
環境変数で、使用するバージョンのJava Development Kit (JDK)のJavaインタプリタを見つけることができます。
表4-4に、oraxml
のコマンドライン・オプションを示します。
表4-4oraxmlのコマンドライン・オプション
オプション | 用途 |
---|---|
- |
ヘルプ・メッセージを出力します。 |
- |
バージョン番号の出力 |
- |
入力ファイルが整形式かどうかの確認 |
- |
DTD検証を使用した入力ファイルの検証 |
- |
スキーマ検証を使用した入力ファイルの検証 |
- |
出力ログ・ファイルへのエラーの書込み |
- |
入力XMLファイルの圧縮 |
- |
入力圧縮ファイルの解凍 |
- |
入力ファイルのエンコーディングの出力 |
- |
警告の表示 |
たとえば、$ORACLE_HOME/xdk/demo/java/parser/common
ディレクトリに変更します。コマンドラインで次のコマンドを実行することにより、文書family.xml
がfamily.dtd
に対して妥当であるかどうかを検証できます。
oraxml -dtd -enc family.xml
出力は次のとおりです。
The encoding of the input file: UTF-8 The input XML file is parsed without errors using DTD validation mode.
W3C標準ライブラリorg.w3c.dom
では、Document
クラスと、DOMのコンポーネント用のクラスが定義されています。Oracle XML Parserには、標準のDOM APIが組み込まれており、W3C DOMの勧告に準拠しています。org.w3c.dom
とともに、Oracle XML Parsingには、DOM APIを実装するクラスが組み込まれており、これらを拡張して文書フラグメントの出力や名前空間情報の取得などの機能を提供しています。
内容は次のとおりです。
XMLアプリケーションにDOMベースのコンポーネントを実装するには、次のクラスを使用します。
oracle.xml.parser.v2.DOMParser
このクラスは、W3C勧告に準拠したXML 1.0のパーサーを実装します。DOMParser
はXMLParser
を拡張するため、XMLParser
のすべてのメソッドはDOMParser
で使用できます。
関連項目:
oracle.xml.parser.v2.XMLDOMImplementation
このクラスにはSDOMの作成に使用されるファクトリ・メソッドが含まれます。
関連項目:
DOMNamespace
およびDOM2Namespace
クラスも利用できます。これらのクラスは、$ORACLE_HOME/xdk/demo/java/parser/dom
に含まれているサンプル・プログラムです。
プログラムDOMSample.java
では、入力XML文書の解析およびDOMを介したアクセスの基本手順を示します。DOMSample.java
は、入力としてXMLファイルを受け取って解析し、DOMツリー内の要素と属性を出力します。
手順は次のとおりです。この手順で、使用可能なメソッドおよびインタフェースを示します。
表4-5に、DOMParser
の構成メソッドの概要を示します。
表4-5 DOMParser構成メソッド
メソッド | 用途 |
---|---|
|
外部エンティティとDTDをロードするためのベースURLを設定します。XML文書が |
|
解析時に使用するDTDを指定します。 |
|
エラーと警告の出力の出力ストリームを作成します。 |
|
入力XML文書内の空白を保持するようにパーサーに指示します。 |
|
パーサーの検証モードを設定します。表4-1に、このメソッドで使用できるフラグを示します。 |
|
パーサーが警告を出力するかどうかを指定します。 |
表4-6に、XMLDocument
クラスが実装するインタフェースの概要を示します。
表4-6 XMLDocumentにより実装されるいくつかのインタフェース
インタフェース | インタフェースによって定義されるもの |
---|---|
|
文書ツリー内の単一ノードと、ノードをアクセスおよび処理するためのメソッド。 |
|
XML文書全体を表す |
|
XML要素を表す |
表4-7に、DOMのツリー・ノードの取得および操作のためのメソッドの概要を示します。
表4-7 DOMツリー・ノードの取得および操作のためのメソッド
メソッド | 用途 |
---|---|
|
このノードが要素である場合はその属性を含む |
|
特定のレベルの特定のタグ名と一致するすべての要素を再帰的に取得します。このメソッドでは、任意のタグと一致する |
|
要素の拡張名を取得します。このメソッドは、 |
|
この要素のローカル名を取得します。要素名が |
|
このノードの名前空間URIを取得するか、名前空間URIが指定されていない場合は |
|
DOMツリーのノードの名前を取得します。 |
|
タイプに応じて、このノードの値を取得します。このノードは |
|
要素の名前空間の接頭辞を取得します。 |
|
要素の修飾名を取得します。要素名が |
|
DOMツリー内の要素の名前を取得します。 |
この項では、プラガブルで拡張性のあるDOM (SDOM)の作成方法および使用方法について説明します。
内容は次のとおりです。
SDOMは、データとは別にDOM APIを持ちます。基礎となるデータは、内部データまたはプラグイン・データのいずれかで、いずれの場合もバイナリXML形式を使用できます。
内部データは、解析されていないXMLテキストです。プラグインするには、内部データをバイナリXMLとして保存し、DOMParser
によって解析する必要があります。解析済バイナリXMLは、DOM APIレイヤーのInfoSetReader
にプラグインされます。InfosetReader
引数は、基礎となるXMLデータへのインタフェースです。
プラグイン・データは、解析済で、プロセッサ間で転送可能なXMLテキストです。
SDOMを作成するには、XMLDOMImplementation
オブジェクトでInfosetReader
APIを介してXMLデータをプラグ・インします。次に例を示します。
public Document createDocument(InfosetReader reader) throws DOMException
InfosetReader
APIはBinXMLStream
の上位に実装されます。XMLデータの他の形式のオプションのアダプタ(dom4j、JDOM、Java Database Connectivity (JDBC)など)もサポートされます。独自の実装もプラグインできます。
InfosetReader
は、拡張性のあるDOM APIレイヤーおよび基礎となるデータ間のインタフェースとして機能します。XMLデータにアクセスするのは、一般的なストリームベースのPull APIです。InfosetReader
は、XMLストリームからシーケンシャルなイベントを取得し、これらのイベントから状態およびデータの問合せを実行します。次のコードでは、XMLデータがスキャンされ、すべての要素のQName
および属性が取得されます。
InfosetReader reader; While (reader.hasNext()) { reader.next(); if (reader.getEventType() == START_ELEMENT) { QName name = reader.getQName(); TypedAttributeList attrList = reader.getAttributeList(); } }
InfosetReader
APIでは次の操作がサポートされます。
コピー(オプションですが、BinXMLStream
のInfosetReader
では常にサポートされます)
文書間のDOMのシャドウ・コピーをサポートするには、Clone
メソッドを使用してInfosetReader
の新規コピーを作成し、スレッドを安全にします。詳細は、「シャドウ・コピーの使用」を参照してください。
フォーカスの移動(オプション)
遅延マテリアライズをサポートするために、InfosetReader
は、offset
によって指定されたどの場所にもフォーカスを移動できます。
If (reader.hasSeekSupport())
reader.seek(offset);
詳細は、「遅延マテリアライズの使用」を参照してください。
InfosetWriter
は、データの書込みをサポートするInfosetReader
APIの拡張です。XDKでは、バイナリXMLの上位でInfosetWriter
が実装されます。この実装は変更できません。
XMLテキストから拡張性のあるDOMを作成するには、DOMParser
の実行前に、XMLテキストをバイナリXMLまたはバイナリXMLへの参照として保存する必要があります。
XMLテキストをバイナリXMLとして保存するには、次の例のようにdoc.save
引数をfalse
に設定します。
XMLDocument doc;
InfosetWriter writer;
doc.save(writer, false);
writer.close();
データ・ソースがデシリアライズに使用可能と判明している場合は、doc.save
引数をtrue
に設定して実際のデータのかわりにバイナリXMLのセクション参照を保存できます。
関連項目:
遅延マテリアライズを使用して、空のDOMをプラグインできます。それにより、必要な場合はデータを取り出せ、不要になったらノードを解放(参照解除)できます。SDOMは、手動ノード参照解除も自動ノード参照解除もサポートします。
内容は次のとおりです。
プラグインDOMアーキテクチャは、ツリーのルートとして単一のDocument
ノードを含む空のDOMを作成します。残りのDOMツリーは、後でアクセスして拡張できます。ノードには拡張されない子や兄弟関係のノードがある場合もありますが、親および祖先は常に拡張されます。DOMは追加データを取り出して次のノードを作成できるように、各ノードは次のノードのInfoSetReader.Offset
プロパティを保持します。
アクセス・メソッド・タイプによっては、DOMノードは戻されたノードのセット以上に拡張する場合もあります。
アクセス方法 | 説明 |
---|---|
DOMナビゲーション |
最初の子や、最後の子、親、前後の兄弟関係などの近隣のノードへのアクセスを可能にします。ノードの作成が必要な場合は、ドキュメント内の順に行われます。 |
識別子(ID)索引付け |
DTDまたはXMLスキーマは、型IDでノードを指定できます。DOMがIDの索引付けをサポートする場合、それらのノードは、索引を使用して直接取出し可能になります。拡張性のあるDOMでは、索引による取得で、前のすべてのノードが拡張されるわけではありませんが、祖先のノードは生成されます。 |
Xpath式 |
XPath評価により、メモリー内のすべての中間ノードが生成されます。たとえば、子孫の軸「//」により全体のサブツリーが拡張されますが、評価後に解放されるものもあります。 |
自動ノード参照解除を使用するには、PARTIAL_DOM
属性をBoolean.TRUE
に設定します。
DOMナビゲーション・サポートでは、ノード間に追加リンクが必要です。自動参照解除モードでは、ガベージ・コレクション時に弱いリンクが自動的に参照解除されます。
リンクの重要性に基づいてノードが解放されます。親ノードへのリンクは削除されません。祖先が有効範囲内の名前空間のコンテキストを提供し、InfosetReader
などのストリームAPIを使用して削除済の親ノードを取得するのは難しいためです。
SDOMツリーでは、親および前の兄弟関係ノードへのリンクは強く、子および次の兄弟関係ノードへのリンクは弱いです。JVMがノードを解放しても、それらへの参照は基礎となるデータで使用可能であるため、必要な場合は再作成できます。
手動ノード参照解除を使用するには、属性PARTIAL_DOM
をBoolean.FALSE
に設定して、プラグインXMLデータを使用してSDOMを作成します。
手動参照解除モードでは、弱参照はありません。アプリケーションは、DOMツリーから文書フラグメントを明示的に参照解除します。アプリケーションが確定的な順序でデータを処理する場合、ノードの解放と再作成を繰り返し行う余分なオーバーヘッドは回避することをお薦めします。
他のすべてのノードからノードを手動で参照解除するには、freeNode()
を起動します。次に例を示します。
Element root = doc.getDocumentElement();
Node item = root.getFirstChild();
While (item != null)
{
processItem(item);
Node tmp = item;
item = item.getNextSibling();
((XMLNode)tmp).freeNode();
}
ノードの参照解除によって、SDOMツリーからノードは削除されません。ノードは、その親や兄弟関係からアクセスおよび再作成可能です。ただし、ノードの参照解除後にノードにアクセスすると、ノードを保持する変数によってエラーがスローされます。
注意:
拡張性のないDOMではfreeNode
の起動は適用されません。
シャドウ・コピーでは、DOMノードでデータを共有することによってデータのレプリケーションを回避します。
XML処理の共通の操作であるクローン作成は、SDOMでは遅延で行うことができます。つまり、copy
メソッドでコピーされる部分のルート・ノードのみが作成され、必要に応じてサブツリーが拡張されます。
DOMノード自体は共有されません。基礎となるデータは共有されます。DOM仕様では、クローンとそのオリジナルではノードIDおよび親ノードを別のものにする必要があります。
DOM APIは、ノードの追加および削除、値の設定、削除、変更および挿入などの更新操作をサポートします。DOMがプラグインXMLデータで作成されると、基礎となるデータはDOMの外部とみなされます。DOM更新は、DOM APIから表示可能ですがデータ・ソースは同一のままです。通常の更新操作は使用可能ですが、相互に妨害はしません。
変更済のDOMを永続にするには、DOMを明示的に保存する必要があります。保存によって変更がオリジナル・データとマージされ、永続格納にデータがシリアライズされます。変更したDOMを明示的に保存しない場合は、トランザクションを終了すると変更が失われます。
XMLテキストがDOMParser
で解析され、SDOMを作成するよう構成されている場合、内部データはバイナリXMLの形式でキャッシュされ、DOM APIレイヤーは内部データの上位で構築されます。バイナリXMLはDOMノードよりさらにコンパクトであるため、これによりスケーラビリティが増大されます。
追加のスケーラビリティに関しては、SDOMはPageManager
インタフェースを介してバイナリ・データのバックエンド格納を使用できます。バイナリ・データは、使用していないメモリーと交換可能です。
次のコードでは、PageManager
インタフェースの使用方法を示します。
DOMParser parser = new DOMParser(); parser.setAttribute(PARTIAL_DOM, Boolean.TRUE); //enable SDOM parser.setAttribute(PAGE_MANAGER, new FilePageManager("pageFile")); ... // DOMParser other configuration parser.parse(fileURL); XMLDocument doc = parser.getDocument();
PageManager
インタフェースを使用しない場合、パーサーはバイナリXMLとして文書全体をキャッシュします。
XMLDOMImplementation
クラスを使用してDOMを作成する場合、XMLDOMImplementation
クラスのsetAttribute
メソッドを使用することによって、異なるアプリケーション用にDOMを構成し、効率を最大にできます。
public void setAttribute(String name, Object value) throws IllegalArgumentException
SDOMの場合、PARTIAL_DOM
およびACCESS_MODE
属性に対してsetAttribute
を起動します。
注意:
新規の属性値が影響するのは次のDOMであり、現在のものではありません。したがって、XMLDOMImplementation
のインスタンスを使用して、別の構成でDOMを作成できます。
この属性によって、作成されるDOMが部分的(つまり、拡張性がある)かどうかが決まります。この属性の値がTRUE
の場合、作成されるDOMは拡張性があります(つまり、使用されていないノードは解放され、必要に応じて再作成されます)。この属性の値がFALSE
の場合、作成されるDOMは拡張性がありません。
この属性(SDOMおよび拡張性のないDOMの両方に適用される)は、作成されるDOMへのアクセスを制御します。ACCESS_MODE
の値を最も制限の弱いものから強いものの順に示します。
値 | DOMアクセス | パフォーマンス上の利点 |
---|---|---|
|
すべての更新操作が許可されます。これはデフォルト値で、XDK DOM実装での下位互換性用です。 |
|
|
DOM更新操作は許可されません。ノードの作成(クローン作成など)は、新規ノードがDOMツリーに追加されない場合にのみ許可されます。 |
書込みバッファは作成されません。 |
|
前方ナビゲーション(たとえば、 |
前の兄弟関係リンクは作成されません。 |
|
SAXイベント・アクセスのような、文書内の順でのノードのストリームに限定されます。 現在のノードは、文書内の順で最後にアクセスされたノードです。アプリケーションは変数内にノードを保持し、再度アクセスできますが、DOMメソッドを使用して現在のノードより前のノード(親または祖先以外)にアクセスすると、エラーが発生します。次に例を示します。
|
DOMでは、親リンクのみ保持され、ノードの位置は保持されません。したがって、開放されたノードを再作成する必要はありません。 |
注意:
Fast Infosetは入力にのみ使用します。出力には、CSXまたはXTIを使用します。
XDK/JにFast Infosetを使用するモデルにより、JavaでXMLコンテンツを使用中にFast Infoset技術を使用できます。この例では、シリアライザを使用してXMLデータをFastInfoset BinaryStream
にエンコードします。
public com.sun.xml.fastinfoset.sax.SAXDocumentSerializer getSAXDocumentSerializer(); public com.sun.xml.fastinfoset.stax.StAXDocumentSerializer getStAXDocumentSerializer();
クラスoracle.xml.scalable.BinaryStream
は、バッファ管理と抽象ページI/Oビューを提供するデータ管理コンポーネントで、様々なタイプのデータ・ストレージのデコードをサポートします。
BinaryStream
のInfosetReaderは、DOMでバイナリからデータを読み取るためのoracle.xml.scalable.InfosetReader
の実装です。この実装により、基本的なデコーダsun.com.xml.fasterinfoset.Decoder
が拡張され、シーク操作およびスキップ操作のサポートが追加されます。
Fast InfosetをStreaming API for XML (StAX)およびSAXとともに使用して、DOMを作成できます。SDOMを作成するために、前の例および次の例のルーチンを使用できます。
String xmlFile, fiFile; FileInputStream xin = new FileInputStream(new File(xmlFile)); XML_SAX_FI figen = new XML_SAX_FI(); FileOutputStream outfi = new FileOutputStream(new File(fiFile)); figen.parse(xin, outfi); outfi.close(); import oracle.xml.scalable.BinaryStream; BinaryStream stream = BinaryStream.newInstance(SUN_FI); stream.setFile(new File(fiFile)); InfosetReader reader = stream.getInfosetReader(); XMLDOMImplementation dimp = new XMLDOMImplementation(); dimp.setAttribute(XMLDocument.SCALABLE_DOM, Boolean.TRUE); XMLDocument doc = (XMLDocument) dimp.createDocument(reader);
このアプリケーションでは、SDOMを作成および使用します。
XMLDOMImplementation domimpl = new XMLDOMImplementation(); domimpl.setAttribute(XMLDocument.SCALABLE_DOM, Boolean.TRUE); domimpl.setAttribute(XMLDocument.ACCESS_MODE,XMLDocument.UPDATEABLE); XMLDocument scalableDoc = (XMLDocument) domimpl.createDocument(reader);
次のアプリケーションでは、「バイナリXML with Javaの使用」で説明されているバイナリXMLに基づいてSDOMを作成および使用します。
BinXMLProcessor proc = BinXMLProcessorFactory.createProcessor(); BinXMLStream bstr = proc.createBinXMLStream(); BinXMLEncoder enc = bstr.getEncoder(); enc.setProperty(BinXMLEncoder.ENC_SCHEMA_AWARE, false); SAXParser parser = new SAXParser(); parser.setContentHandler(enc.getContentHandler()); parser.setErrorHandler(enc.getErrorHandler()); parser.parse(BinXMLUtil.createURL(xmlfile)); BinXMLDecoder dec = bstr.getDecoder(); InfosetReader reader = dec.getReader(); XMLDOMImplementation domimpl = new XMLDOMImplementation(); domimpl.setAttribute(XMLDocument.SCALABLE_DOM, Boolean.TRUE); XMLDocument currentDoc = (XMLDocument) domimpl.createDocument(reader);
XDKでは、DOMレベル3のコア仕様、W3C勧告をサポートしています。
関連項目:
DOMレベル3の詳細は、http://www.w3.org/TR/DOM-Level-3-Core/
を参照してください
DOM2Namespace.java
プログラムは、パーサーの単純な使用方法とDOM APIへの名前空間による拡張を示します。プログラムは、XML文書を受け取って解析し、文書内の要素と属性を出力します。
この項には、DOM2Namespace.java
プログラムのコードの一部が含まれています。詳細は、プログラム自体を参照してください。
「基本的なDOM解析の実行」の最初の4つの手順(パーサー作成からgetDocument()
の起動まで)は、基本的にDOM2Namespace.java
の場合も同じです。主な違いは、DOMツリーの出力です(手順5)。DOM2Namespace.java
プログラムでは、かわりに次のようにします。
// Print document elements printElements(doc); // Print document element attributes System.out.println("The attributes of each element are: "); printElementAttributes(doc);
DOM2Namespace.java
により実装されるprintElements()
メソッドは、getElementsByTagName()
を起動して、DOMツリー内のすべての要素のリストを取得します。次に、リスト内の各アイテムをループし、各Element
をnsElement
にキャストします。各nsElement
について、nsElement.getPrefix()
を起動して名前空間の接頭辞を取得し、nsElement.getLocalName()
を起動してローカル名を取得し、nsElement.getNamespaceURI()
を起動して名前空間URIを取得します。
static void printElements(Document doc) { NodeList nl = doc.getElementsByTagName("*"); Element nsElement; String prefix; String localName; String nsName; System.out.println("The elements are: "); for (int i=0; i < nl.getLength(); i++) { nsElement = (Element)nl.item(i); prefix = nsElement.getPrefix(); System.out.println(" ELEMENT Prefix Name :" + prefix); localName = nsElement.getLocalName(); System.out.println(" ELEMENT Local Name :" + localName); nsName = nsElement.getNamespaceURI(); System.out.println(" ELEMENT Namespace :" + nsName); } System.out.println(); }
printElementAttributes()
メソッドは、Document.getElementsByTagName()
を起動して、DOMツリー内の要素のNodeList
を取得します。次に、各要素をループし、Element.getAttributes()
を起動して要素の属性のリストをNamedNodeMap
という特殊なリストとして取得します。属性リストの各アイテムについて、nsAttr.getPrefix()
を起動して名前空間の接頭辞を取得し、nsAttr.getLocalName()
を起動してローカル名を取得し、nsAttr.getValue()
を起動して値を取得します。
static void printElementAttributes(Document doc) { NodeList nl = doc.getElementsByTagName("*"); Element e; Attr nsAttr; String attrpfx; String attrname; String attrval; NamedNodeMap nnm; int i, len; len = nl.getLength(); for (int j=0; j < len; j++) { e = (Element) nl.item(j); System.out.println(e.getTagName() + ":"); nnm = e.getAttributes(); if (nnm != null) { for (i=0; i < nnm.getLength(); i++) { nsAttr = (Attr) nnm.item(i); attrpfx = nsAttr.getPrefix(); attrname = nsAttr.getLocalName(); attrval = nsAttr.getNodeValue(); System.out.println(" " + attrpfx + ":" + attrname + " = " + attrval); } } System.out.println(); } }
EventSample.java
プログラムは、イベント・リスナーにイベントを登録する方法を示します。たとえば、指定されたDOM要素にノードが追加されると、イベントがトリガーされます。これにより、リスナーがイベントに関する情報を出力します。
この項には、EventSample.java
プログラムのコードの一部が含まれています。詳細は、プログラム自体を参照してください。
EventSample.java
プログラムは次の手順を実行します。
W3C DOM仕様によると、範囲はDocument
、DocumentFragment
またはAttr
のコンテンツの範囲を識別します。範囲によって、範囲の開始と終了に対応する1組の境界点の間にあるコンテンツを選択します。表4-8に、XMLDocument
を介してアクセスできる範囲メソッドを示します。
表4-8 範囲クラスのメソッド
メソッド | 説明 |
---|---|
|
範囲のコンテンツを複製します。 |
|
範囲のコンテンツを削除します。 |
|
範囲が閉じている場合に |
|
範囲が終了するノードを取得します。 |
|
範囲が開始するノードを取得します。 |
|
ノードとそのコンテンツを選択します。 |
|
ノードのコンテンツを選択します。 |
|
範囲の終了を示す属性を設定します。 |
|
範囲の開始を示す属性を設定します。 |
DOMRangeSample.java
プログラムは、範囲で実行できる操作をいくつか示します。この項には、DOMRangeSample.java
プログラムのコードの一部が含まれています。詳細は、プログラム自体を参照してください。
「基本的なDOM解析の実行」の最初の4つの手順(パーサー作成からgetDocument()
の起動まで)は、DOMRangeSample.java
の場合も同じです。DOMRangeSample.java
プログラムは次の手順を実行します。
XDKは、W3C DOMレベル2 Traversal and Range仕様で定義されているNodeFilter
およびTreeWalker
インタフェースを実装します。
ノード・フィルタは、特定のタイプのNode
オブジェクトをフィルタ処理するオブジェクトです。たとえば、エンティティ参照ノードをフィルタ処理によって除外し、要素ノードと属性ノードを受け入れることができます。NodeFilter
インタフェースを実装し、次にNode
オブジェクトをacceptNode()
メソッドに渡すことにより、ノード・フィルタを作成します。通常、acceptNode()
メソッド実装はgetNodeType()
を起動してノードのタイプを取得し、それをELEMENT_TYPE
やATTRIBUTE_TYPE
などの静的変数と比較してから、結果に基づいて表4-9に示された静的フィールドの1つを戻します。
表4-9 NodeFilterインタフェースの静的フィールド
フィールド | 説明 |
---|---|
|
ノードを受け入れます。 |
|
ノードを拒否します。 |
|
この単一ノードをスキップします。 |
TreeWalker
オブジェクトを使用し、whatToShow
フラグおよびTreeWalker
オブジェクトのフィルタで定義されている文書のビューを使用して文書ツリーまたはサブツリーを検索できます。
TreeWalker
オブジェクトを作成するには、次の項目を指定してXMLDocument.createTreeWalker()
メソッドを使用します。
ツリーまたはサブツリーのルート・ノード
論理ビューに含めるノードのタイプを管理するフラグ
ノード・フィルタ(オプション)
エンティティ参照とその子孫を含めるかどうかを決定するフラグ
表4-10で、org.w3c.dom.traversal.TreeWalker
インタフェースのメソッドについて説明します。
表4-10 TreeWalkerインタフェース・メソッド
メソッド | 説明 |
---|---|
|
ツリー・ウォーカーを現在のノードの最初に表示可能な子に移動し、新規ノードを戻します。現在のノードに表示可能な子がない場合は、メソッドは |
|
ツリー・ウォーカーのルート・ノード( |
|
ツリー・ウォーカーを現在のノードの最後に表示可能な子に移動し、新規ノードを戻します。現在のノードに表示可能な子がない場合は、メソッドは |
|
ツリー・ウォーカーを文書内の現在のノードとの相対順序で次に表示可能な子に移動し、新規ノードを戻します。 |
TreeWalkerSample.java
プログラムは、ノード・フィルタとツリー・ウォーカーで実行できる操作をいくつか示します。この項には、TreeWalkerSample.java
プログラムのコードの一部が含まれています。詳細は、プログラム自体を参照してください。
「基本的なDOM解析の実行」の最初の4つの手順(パーサー作成からgetDocument()
の起動まで)は、TreeWalkerSample.java
の場合も同じです。TreeWalkerSample.java
プログラムは次の手順を実行します。
Simple API for XML (SAX)は、イベントベースのXML解析の標準インタフェースです。
内容は次のとおりです。
レベル1およびレベル2のバージョンでリリースされたSAX APIには、次のインタフェースとクラスがあります。
Oracle XML Parserで実装されるインタフェース
アプリケーションで実装する必要のあるインタフェース(表4-11を参照)
標準SAXクラス
org.xml.sax.helper
パッケージのSAX 2.0ヘルパー・クラス(表4-12を参照)
nul
パッケージ内のデモンストレーション・クラス
表4-11に、アプリケーションで実装する必要のあるSAX 2.0インタフェースをリストし、説明します。
表4-11 SAX 2.0ハンドラ・インタフェース
インタフェース | 説明 |
---|---|
|
XMLパーサーから通知を受信します。主なイベント処理メソッドである |
|
XML文書内のDTD宣言に関する通知を受信します。 |
|
通知および未解析(バイナリ)エンティティを処理します。 |
|
文書内のURIのリダイレクトをサポートします。 |
|
パーサー・エラーを処理します。メソッド |
|
コメントや文字データ(CDATA)セクション境界などの字句情報に関する通知を受信します。 |
表4-12に、SAX 2.0ヘルパー・クラスをリストし、説明します。
表4-12 SAX 2.0ヘルパー・クラス
クラス | 説明 |
---|---|
|
|
|
表4-11のインタフェースのデフォルト実装によるベース・クラス。 |
|
解析中の指定されたポイントでロケータの値の永続スナップショットを作成します。 |
|
XML名前空間をサポートします。 |
|
イベントのストリームを変更するアプリケーションによって使用されるベース・クラス。 |
|
SAXパーサーの動的ロードをサポートします。 |
図4-5に、SAXパーサーの作成方法と、そのパーサーを使用して入力文書を解析する方法を示します。
SAXを使用した入力XML文書の解析の基本手順は次のとおりです。
SAXParser
オブジェクトを作成し、そのプロパティを構成します。
たとえば、検証モードを設定します。構成メソッドについては、表4-5を参照してください。
イベント・ハンドラをインスタンス化します。
アプリケーションで表4-11のハンドラ・インタフェースを実装する必要があります。
XMLパーサーにイベント・ハンドラを登録します。
この手順によって、パーサーは特定のイベントが発生したときに適切なメソッドを起動できます。イベント・ハンドラを登録するためのSAXParser
のメソッドの詳細は、表4-13を参照してください。
SAXParser.parse()
メソッドを使用して入力ドキュメントを解析します。
すべてのSAXインタフェースは、同期操作を前提としています。そのため、解析メソッドは解析が完了するまで結果を戻しません。リーダーは、次のイベントを通知する前にイベント・ハンドラのコールバックが結果を戻すまで待機する必要があります。
SAXParser.parse()
メソッドが起動された場合、プログラムでは、アプリケーションで実装された複数のコールバック・メソッドの1つを起動します。メソッドは、イベント・ハンドラで実装されたContentHandler
、ErrorHandler
、DTDHandler
およびEntityResolver
インタフェースにより定義されます。たとえば、アプリケーションは、開始要素を検出した際にstartElement()
メソッドを起動できます。
表4-13に、イベント・ハンドラを登録するためのSAXParser
のメソッドをリストして説明し、各メソッドを使用する場合について説明します。アプリケーションは、解析処理中に新規または別のハンドラを登録できます。SAXパーサーは、新たに登録されたハンドラの使用をただちに開始する必要があります。
表4-13 イベント・ハンドラを登録するためのSAXParserのメソッド
メソッド | 説明 |
---|---|
|
コンテンツ・イベント・ハンドラをアプリケーションに登録します。
|
|
DTDイベント・ハンドラをアプリケーションに登録します。 アプリケーションでDTDハンドラを登録しない場合、SAXパーサーにより報告されるDTDイベントは無視され、警告は出力されません。 |
|
エラー・イベント・ハンドラをアプリケーションに登録します。 アプリケーションでエラー・ハンドラを登録しない場合、SAXパーサーにより報告されるすべてのエラー・イベントは無視され、警告は出力されません。予想外の不具合を回避するため、すべてのSAXアプリケーションにエラー・ハンドラを実装することを強くお薦めします。 |
|
エンティティ・リゾルバをアプリケーションに登録します。 アプリケーションでエンティティ・リゾルバを登録しない場合、 |
SAXSample.java
サンプル・プログラムは、SAX解析の基本手順を示します。SAXSample
クラスはHandlerBase
を拡張します。プログラムは、入力としてXMLファイルを受け取って解析し、ファイルのコンテンツに関する情報を出力します。
SAXSample.java
プログラムは次の手順(プログラムのコード部分とともに示す)を実行します。
SAX2Namespace.java
サンプル・プログラムでは、XMLDefaultHandler
というイベント・ハンドラをorg.xml.sax.helpers.DefaultHandler
クラスのサブクラスとして実装します。ContentHandler
インタフェースを実装する最も簡単な方法は、org.xml.sax.helpers.DefaultHandler
クラスを拡張することです。DefaultHandler
クラスは、イベントを処理するためのデフォルトの動作をいくつか提供しますが、一般的な動作は何も行わないことです。
SAX2Namespace.java
プログラムでは、関連するイベントに対してのみメソッドをオーバーライドします。具体的には、XMLDefaultHandler
クラスはstartElement()
およびendElement()
という2つのメソッドのみ実装します。SAXParser
は、XML文書内に新規要素を検出するとstartElement
イベントをトリガーし、startElement()
メソッドが要素の名前空間情報を出力します。
SAX2Namespace.java
サンプル・プログラムは次の手順(プログラムのコード部分とともに示す)を実行します。
単純なSAXパーサーをXMLTokenizer
クラスのインスタンスとして作成し、パーサーを使用して入力XMLをトークン化できます。表4-14に、このクラスの有用なメソッドを示します。
表4-14 XMLTokenizerメソッド
メソッド | 説明 |
---|---|
|
XMLトークン化機能の新規トークンを登録します。 |
|
エラーの出力ストリームを登録します。 |
|
入力XMLをトークン化します。 |
Tokenizer
機能のあるSAXパーサーは、XMLToken
インタフェースを実装します。XMLToken
のコールバック・メソッドはtoken()
です。このメソッドは、XMLトークンおよび対応する値を受け取り、アクションを実行します。たとえば、トークン名に続いてトークンの値を出力するようにtoken()
を実装できます。
Tokenizer.java
サンプル・プログラムでは、入力としてXML文書を受け取って解析し、XMLトークンのリストを出力します。プログラムでは、次の手順(プログラムのコード部分とともに示す)を実行するdoParse()
メソッドを実装します。
JAXPを使用すると、JavaプログラムでSAXおよびDOMパーサーとXSLTプロセッサを使用できます。
内容は次のとおりです。
JAXPは、パーサーのプラガビリティのためのthinレイヤーを提供する抽象クラスで構成されます。Oracleは、Sun社のリファレンス実装に基づいてJAXPを実装しています。
表4-15に、JAXPを構成するパッケージをリストし、説明します。
表4-15 JAXPパッケージ
パッケージ | 説明 |
---|---|
|
DOM 2.0およびSAX 1.0パーサーの標準APIを提供します。 |
|
XML変換の処理と、ソースから結果への変換の実行のための汎用APIを定義します。 |
|
DOM固有の変換APIを提供します。 |
|
SAX2固有の変換APIを提供します。 |
|
ストリーム固有およびURI固有の変換APIを提供します。 |
ファクトリ設計パターンに依存して、JAXPを使用して新規SAXパーサー・エンジンを作成できます。図4-6に、基本プロセスを示します。
JAXPを介したSAXでの解析の基本手順は、次のとおりです。
SAXParserFactory
クラスで新規SAXパーサー・ファクトリを作成します。SAXParser
)オブジェクトをファクトリから作成します。ファクトリ設計パターンに基づき、JAXPを使用して新規DOM文書ビルダー・エンジンを作成できます。図4-7に、基本プロセスを示します。
JAXPを介したDOMでの解析の基本手順は、次のとおりです。
DocumentBuilderFactory
クラスで新規DOMパーサー・ファクトリを作成します。DocumentBuilder
)オブジェクトをファクトリから作成します。JAXPを介したXML変換の基本手順は、次のとおりです。
TransformerFactory
クラスで新規トランスフォーマ・ファクトリを作成します。JAXPExamples.java
プログラムは、JAXPを使用した解析の基本手順を示します。このプログラムは、次のメソッドを実装し、これらのメソッドを使用して/jaxp
ディレクトリ内のXMLファイルに対して解析および追加処理を実行します。
basic()
identity()
namespaceURI()
templatesHandler()
contentHandler2contentHandler()
contentHandler2DOM()
reader()
xmlFilter()
xmlFilterChain()
プログラムでは、サンプルXMLファイルjaxpone.xml
およびjaxpone.xsl
のURLを作成し、前述のメソッドを順番に起動します。デモの基本設計は次のとおりです(スペースを節約するために、basic()
メソッドのみ示しています)。
public class JAXPExamples { public static void main(String argv[]) throws TransformerException, TransformerConfigurationException, IOException, SAXException, ParserConfigurationException, FileNotFoundException { try { URL xmlURL = createURL("jaxpone.xml"); String xmlID = xmlURL.toString(); URL xslURL = createURL("jaxpone.xsl"); String xslID = xslURL.toString(); // System.out.println("--- basic ---"); basic(xmlID, xslID); System.out.println(); ... } catch(Exception err) { err.printStackTrace(); } } // public static void basic(String xmlID, String xslID) throws TransformerException, TransformerConfigurationException { TransformerFactory tfactory = TransformerFactory.newInstance(); Transformer transformer = tfactory.newTransformer(new StreamSource(xslID)); StreamSource source = new StreamSource(xmlID); transformer.transform(source, new StreamResult(System.out)); } ... }
プログラムJAXPExamples.java
のreader()
メソッドでは、次の手順(プログラムのコード部分とともに示す)を使用して、SAXでXML文書を解析する簡単な方法を示します。
JAXPでは、次のタイプの入力を変換できます。
XML文書
スタイルシート
oraContentHandler.java
に定義されているContentHandler
クラス
JAXPを使用して基本的な変換を実行できます。次に例を示します。
identity()
メソッドを使用して、出力XML文書が入力XML文書と同じになる変換を実行できます。
xmlFilterChain()
メソッドを使用して、連鎖内の3つのスタイルシートを適用できます。
インタフェースSource
の任意のクラスをインタフェースResult
のクラスに(DOMSource
をDOMResult
に、StreamSource
をStreamResult
に、SAXSource
をSAXResult
に、など)変換できます。
プログラムJAXPExamples.java
のbasic()
メソッドでは、次の手順(プログラムのコード部分とともに示す)を使用して基本的なXSLT変換を実行する方法を示します。
XDKでは、SAXまたはDOMを使用してXMLを解析し、解析したデータを圧縮バイナリ・ストリームに書き込むことができます。反対に、バイナリ・ストリームを解凍してXMLデータを再構築することもできます。
内容は次のとおりです。
プログラムDOMCompression.java
では、DOMの圧縮の基本手順を示します。最も重要なDOMの圧縮メソッドはXMLDocument.writeExternal()
で、オブジェクトに関する情報でバイナリ圧縮ストリームを作成することにより、オブジェクトの状態を保存します。
DOMCompression.java
プログラムでは、次の手順(プログラムのコード部分とともに示す)を使用します。
プログラムDOMDeCompression.java
では、DOMの解凍の基本手順を示します。最も重要なDOMの解凍メソッドはXMLDocument.readExternal()
で、writeExternal()
メソッドにより書き込まれた情報(圧縮ストリーム)を読み取り、オブジェクトを復元します。
DOMDeCompression.java
プログラムでは、次の手順(プログラムのコード部分とともに示す)を使用します。
SAXCompression.java
プログラムは、SAXを使用してファイルを解析し、圧縮ストリームをファイルに書き込む基本手順を示します。重要なクラスはCXMLHandlerBase
で、SAXイベントに基づいてXMLデータを圧縮するSAX Handler
です。SAX圧縮を使用するには、このインタフェースを実装し、Parser.setDocumentHandler()
を起動してSAXパーサーに登録します。
SAXCompression.java
プログラムでは、次の手順(プログラムのコード部分とともに示す)を使用します。
XMLNode
クラスのselectNodes()
メソッドを使用して、XSLが許可する選択パターンに基づいてDOMツリーまたはサブツリーからコンテンツを抽出できます。selectNodes()
のオプションの2つ目のパラメータを使用して、名前空間の接頭辞を解決できます。つまり、接頭辞付きの展開された名前空間URLを戻します。XMLElement
クラスはNSResolver
を実装するため、XMLElement
オブジェクトの参照は、2つ目のパラメータとして送信できます。XMLElement
は、入力文書に基づいて接頭辞を解決します。名前空間の定義をオーバーライドする場合、NSResolver
インタフェースを使用できます。
例4-4のサンプル・コードでは、selectNodes()
の使用方法を示します。
プログラムをテストするには、例4-4のコードを使用してファイルを作成してから、$ORACLE_HOME/xdk/demo/java/parser/
common
ディレクトリ内でコンパイルします。ファイル名family.xml
をパラメータとしてプログラムに渡して、<family>
ツリーを検索します。出力は次のようになります。
% java selectNodesTest family.xml Sarah Bob Joanne Jim
ここで、次のコードを実行して、文書内のすべての<member>
要素のmemberid
属性の値を判断します。
% java selectNodesTest family.xml //member/@memberid m1 m2 m3 m4
例4-4 selectNodes()を使用したDOMツリーのコンテンツの抽出
// // selectNodesTest.java // import java.io.*; import oracle.xml.parser.v2.*; import org.w3c.dom.Node; import org.w3c.dom.Element; import org.w3c.dom.Document; import org.w3c.dom.NodeList; public class selectNodesTest { public static void main(String[] args) throws Exception { // supply an xpath expression String pattern = "/family/member/text()"; // accept a filename on the command line // run the program with $ORACLE_HOME/xdk/demo/java/parser/common/family.xml String file = args[0]; if (args.length == 2) pattern = args[1]; DOMParser dp = new DOMParser(); dp.parse(DemoUtil.createURL(file)); // include createURL from DemoUtil XMLDocument xd = dp.getDocument(); XMLElement element = (XMLElement) xd.getDocumentElement(); NodeList nl = element.selectNodes(pattern, element); for (int i = 0; i < nl.getLength(); i++) { System.out.println(nl.item(i).getNodeValue()); } // end for } // end main } // end selectNodesTest
ユーザーがクライアント側Javaフォームに入力でき、XML文書を取得できるプログラムを作成するために、Javaプログラムに次の変数を含めることができます。
String firstname = "Gianfranco"; String lastname = "Pietraforte";
この情報をXML文書に挿入するには、次のいずれかの方法を使用します。
XML文書を文字列で作成し、解析します。次に例を示します。
String xml = "<person><first>"+firstname+"</first>"+ "<last>"+lastname+"</last></person>"; DOMParser d = new DOMParser(); d.parse(new StringReader(xml)); Document xmldoc = d.getDocument();
DOM APIを使用して、要素を作成して順番に追加することによりXML文書を作成します。次に例を示します。
Document xmldoc = new XMLDocument(); Element e1 = xmldoc.createElement("person"); xmldoc.appendChild(e1); Element e2 = xmldoc.createElement("firstname"); e1.appendChild(e2); Text t = xmldoc.createText("Larry"); e2.appendChild(t);
単一のDOMツリーでは2番目の方法のみ使用できます。
例4-5では、2つのツリー(e1
の所有者文書はxmldoc1
で、e2
の所有者文書はxmldoc2
)を使用します。appendChild()
メソッドは、単一ツリー内でのみ機能します。したがって、XMLElement.appendChild()
を起動すると、DOM例外WRONG_DOCUMENT_ERR
が発生します。
異なるXML文書間におけるDOM文書のフラグメントまたはDOMノードのコピーおよび貼付けには、XMLDocument.importNode()
メソッド(DOM 2で導入)およびXMLDocument.adoptNode()
メソッド(DOM 3で導入)を使用します。例4-6のコメントでは、この方法を示します。
例4-5 appendChild()の不適切な使用方法
XMLDocument xmldoc1 = new XMLDocument(); XMLElement e1 = xmldoc1.createElement("person"); XMLDocument xmldoc2 = new XMLDocument(); XMLElement e2 = xmldoc2.createElement("firstname"); e1.appendChild(e2);
例4-6 appendChild()を使用した文書のマージ
XMLDocument doc1 = new XMLDocument(); XMLElement element1 = doc1.createElement("person"); XMLDocument doc2 = new XMLDocument(); XMLElement element2 = doc2.createElement("firstname"); // element2 = doc1.importNode(element2); // element2 = doc1.adoptNode(element2); element1.appendChild(element2);
内容は次のとおりです。
DOMParser.parse()
メソッドを起動してXML文書をInputStream
として解析する場合は、DOMParser.setBaseURL()
メソッドを使用してJavaプログラム内で外部DTDを認識します。DOMParser.setBaseURL()
は、DTDが公開されている場所を指します。
DTDのロードと解析の手順は次のとおりです。
XML Parser for Javaには、DOMParser.setDoctype()
メソッドを使用した検証モードと非検証モードでのDTDキャッシュ機能が用意されています。このメソッドでDTDを設定すると、以降の解析で使用するためにパーサーはこのDTDをキャッシュします。
注意:
DTDキャッシュ機能はオプションであり、自動的には有効になりません。
プログラムで、同じDTDを使用して複数のXML文書を解析する必要があるとします。最初のXML文書の解析後、パーサーからDTDを取得し、設定できます。次に例を示します。
DOMParser parser = new DOMParser(); DTD dtd = parser.getDoctype(); parser.setDoctype(dtd);
例4-7では、DOMParser.setDoctype()
を起動してDTDをキャッシュします。
キャッシュされたDTDオブジェクトが検証に対してのみ使用される場合は、DOMParser.USE_DTD_ONLY_FOR_VALIDATION
属性を設定します。
parser.setAttribute(DOMParser.USE_DTD_ONLY_FOR_VALIDATION,Boolean.TRUE);
DTDオブジェクトが検証に使用されない場合、XMLパーサーはDTDオブジェクトをコピーして、結果のDOMツリーに追加します。
例4-7 DTDSample.java
/** * DESCRIPTION * This program illustrates DTD caching. */ import java.net.URL; import java.io.*; import org.xml.sax.InputSource; import oracle.xml.parser.v2.*; public class DTDSample { static public void main(String[] args) { try { if (args.length != 3) { System.err.println("Usage: java DTDSample dtd rootelement xmldoc"); System.exit(1); } // Create a DOM parser DOMParser parser = new DOMParser(); // Configure the parser parser.setErrorStream(System.out); parser.showWarnings(true); // Create a FileReader for the DTD file specified on the command // line and wrap it in an InputSource FileReader r = new FileReader(args[0]); InputSource inSource = new InputSource(r); // Create a URL from the command-line argument and use it to set the // system identifier inSource.setSystemId(DemoUtil.createURL(args[0]).toString()); // Parse the external DTD from the input source. The second argument is // the name of the root element. parser.parseDTD(inSource, args[1]); DTD dtd = parser.getDoctype(); // Create a FileReader object from the XML document specified on the // command line r = new FileReader(args[2]); // Wrap the FileReader in an InputSource, // create a URL from the filename, // and set the system identifier inSource = new InputSource(r); inSource.setSystemId(DemoUtil.createURL(args[2]).toString()); // ******************** parser.setDoctype(dtd); // ******************** parser.setValidationMode(DOMParser.DTD_VALIDATION); // parser.setAttribute // (DOMParser.USE_DTD_ONLY_FOR_VALIDATION,Boolean.TRUE); parser.parse(inSource); // Get the DOM tree and print XMLDocument doc = parser.getDocument(); doc.print(new PrintWriter(System.out)); } catch (Exception e) { System.out.println(e.toString()); } } }
内容は次のとおりです。
オペレーティング・システム・ファイルに格納されたXMLファイルを読み取る場合は、FileReader
クラスを使用しないでください。かわりにXMLパーサーを使用して、文書の文字のエンコーディングが自動的に検出されるようにします。外部エンコーディング情報がないバイナリFileInputStream
の場合、パーサーは、バイト・オーダー・マークおよびXML文書のエンコーディング宣言に基づいて、文字のエンコーディングを自動的に判断します。$ORACLE_HOME/xdk/demo/java/parser/dom
にあるAutoDetectEncoding.java
デモのサンプル・コードを使用して、サポートされている任意のエンコーディングの任意の整形式文書を解析できます。
注意:
仕様のとおりに、文書内に適切なエンコーディング宣言を含めます。setEncoding()
では、入力文書のエンコーディングを設定できません。setEncoding()
はoracle.xml.parser.v2.XMLDocument
と組み合せて使用し、出力用の適切なエンコーディングを設定します。
8ビット・エンコーディングのUnicode (UTF-8)を使用してXMLをデータベースの各国語キャラクタ・ラージ・オブジェクト(NCLOB
)列にロードし、XMLに2つのUTF-8マルチバイト・キャラクタが含まれているとします。
G(0xc2,0x82)otingen, Br(0xc3,0xbc)ck_W
次の処理を行うJavaストアド・ファンクションを作成します。
プログラムは、文字(0xc2
、0x82
)が有効なUTF-8であっても、XMLに無効なUTF-8エンコーディングが含まれているということを示す例外をスローします。問題は、プログラムがOracleResultSet.getAsciiStream()
メソッドを起動すると、文字に異常が発生する可能性があることです。この問題を解決するには、getAsciiStream()
のかわりに、getUnicodeStream()
およびgetBinaryStream()
メソッドを起動します。この方法が機能しない場合は、DOMParser.parse(istr)
を起動する際、文字がパーサーに送信される前に、文字が異常でないことを確認するために出力してみてください。
UTF-8エンコーディングはXML文書には一般的ですが、UTF-8は、通常はJavaのデフォルトのファイル・エンコーディングではありません。デフォルトのファイル・エンコーディングを想定したJavaクラスをプログラムで使用すると、問題が発生する可能性があります。
たとえば、JavaクラスFileWriter
は、実行時環境のデフォルトの文字エンコーディングに依存します。デフォルトの文字エンコーディングで使用できない文字が含まれるXMLファイルに書き込む際にFileWriter
クラスを使用する場合、出力ファイルでは、解析エラーやデータの損失が発生する可能性があります。
このような問題を回避するために、$ORACLE_HOME/xdk/demo/java/parser/dom
のI18nSafeXMLFileWritingSample.java
プログラムに示されている方法を使用します。
特殊文字の出力にはSystem.out.println()
を使用できません。OutputStreamWriter
など、エンコーディングを識別するバイナリ出力ストリームを使用する必要があります。次の例のように、OutputStreamWriter
を構築し、write(char[]
, int
, int)
メソッドを使用して出力します。
/* Java encoding string for ISO8859-1*/ OutputStreamWriter out = new OutputStreamWriter(System.out, "8859_1"); OutputStreamWriter.write(...);
String
に含まれているXML文書を解析するには、まず文字列をInputStream
またはInputSource
オブジェクトに変換する必要があります。
例4-8では、XMLの文字列(xmlDoc
で参照)をバイト配列に変換し、バイト配列をByteArrwayInputStream
に変換して解析します。
PrintWriter
にStringWriter
をラップすることで、前述のコードで作成したXMLDocument
オブジェクトを再び文字列に変換できます。次の例では、次の方法を示します。
例4-8で作成したXMLDocument
オブジェクトを再び文字列に変換するには、PrintWriter
にStringWriter
をラップします。
StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); doc.print(pw); String YourDocInString = sw.toString();
$ORACLE_HOME/xdk/demo/java/parser/dom
にあるParseXMLFromString.java
は、XML文書を文字列として作成し、それを解析する完全なプログラムです。
例4-8 文字列内のXMLの変換
// create parser DOMParser parser=new DOMParser(); // create XML document in a string String xmlDoc = "<?xml version='1.0'?>"+ "<hello>"+ " <world/>"+ "</hello>"; // convert string to bytes to stream byte aByteArr [] = xmlDoc.getBytes(); ByteArrayInputStream bais = new ByteArrayInputStream(aByteArr,0,aByteArr.length); // parse and get DOM tree DOMParser.parse(bais); XMLDocument doc = parser.getDocument();
例4-9に、アクセント付き文字(é
など)を含むXML文書の解析方法の1つを示します。
XMLファイルを解析しようとすると、パーサーによって、無効なUTF-8エンコーディングであるという例外がスローされることがあります。エンコーディングはUnicodeの文字番号表現をディスクに書き込むために使用されるスキームです。エンコーディングを明示的にUTF-8に設定した場合、またはエンコーディングを指定しない場合、パーサーはアクセント付き文字(127より大きいASCII値の文字)をUTF-8マルチバイト文字列の最初のバイトとして解析します。後続のバイトが有効なUTF-8文字列を構成していない場合、エラーが発生します。
このエラーは、XMLエディタがファイルをUTF-8エンコーディングを使用して保存していないことを意味します。エディタでファイルをISO-8859-1(西欧ASCII)エンコーディングで保存した可能性があります。次の要素をXML文書の最上部に追加しても、エディタはファイルを表すバイトをUTF-8エンコーディングを使用してディスクに書き込みません。
<?xml version="1.0" encoding="UTF-8"?>
1つの解決策として、アクセント付き文字は、XML文書内でÙ
のように16進または10進フォーマットで表すと読み取ることができます。この方法を使用しない場合は、XMLファイルの作成時に使用したキャラクタ・セットに基づいてエンコーディングを設定できます(ISO-8859-1など)。
例4-9 アクセント付き文字を含む文書の解析
DOMParser parser=new DOMParser(); parser.setPreserveWhitespace(true); parser.setErrorStream(System.err); parser.setValidationMode(false); parser.showWarnings(true); parser.parse (new FileInputStream(new File("file_with_accents.xml")));
タグ名に特殊文字(&
、$
、#
など)が含まれる場合、パーサーは無効な文字のエラーを表示します。
新規XML文書を作成している場合、無効なNameChar
文字を含まないタグ名を選択します。たとえば、タグ名が会社名に基づき、ある会社の名前がA&Bの場合、無効なタグ<A&B>
のかわりに、<A_B>
、<AB>
または<A_AND_B>
を選択します。
データベース表などの外部データ・ソースからXMLを生成する場合、次のようになります。
XML 1.0は、この問題には対応していません。
XML 1.1では、データ型XMLType
は、DBMS_XMLGEN
パッケージでsetConvertSpecialChars
およびconvert
ファンクションを提供することで、この問題に対処しています。
これらのファンクションを使用して、Structured Query Language (SQL)名とXML名の特殊文字の使用を制御できます。SQLからXMLに名前をマップするファンクションでは、無効なXML NameChar
文字は_XHHHH_
という形式(HHHH
は無効な文字のUnicode値)でエスケープされます。たとえば、表名V$SESSION
はXMLの名前V_X0024_SESSION
にマップされます。
無効な文字のエスケープは、名前を他の場所に再ロードできるようにシリアライズする方法を提供します。