XMLデータへプログラムからのアクセスを行うための規格である DOM (Document Object Model) を学習するとともに,XMLへの理解を一層深める.今回は前回に引き続き,DOMを扱うための基本的事項を学ぶ.
前回は XML プロセッサ Xerces について,その考え方と基本的なプログラミングを学習した.以下は,指定された XML ファイルを読み込んで主記憶中に DOM 木を構築して終了する,単純な DOM プログラムである.
1: import org.w3c.dom.*; 2: import org.apache.xerces.parsers.*; 3: 4: class DomParserDemo { 5: public static void main(String[] args) { 6: try { 7: // DOM パーサの生成 8: DOMParser parser = new DOMParser(); 9: // XML 文書の取得 10: parser.parse(args[0]); 11: // Document インスタンスの取得 12: Document doc = parser.getDocument(); 13: } catch (Exception e) { 14: e.printStackTrace(); 15: } 16: } 17: }
プログラムの概要は以下の通りである. 1〜2行目は C 言語の include 文に相当するものであり,プログラム内で利用しているクラスのインタフェースに関する情報がどこにあるかを指定するものである. org.w3c.dom.* の * は,org.w3c.dom.Attr, org.w3c.Element などの複数のインタフェースを簡潔に一文で指定するための機能である. 1行目の org.w3c.dom は,XML データ用の Java のパッケージに関する import 文である. このパッケージの概要は,http://java.sun.com/j2se/1.4/ja/docs/ja/api/org/w3c/dom/package-summary.htmlなどで見ることができる. 2行目の org.apache.xerces.parser は,今回用いている Xerces のインタフェースを指定している.
4〜17行目が実際のプログラムである. main 関数は引数として文字列をとり(5行目),6〜15行目を実行する. try {...} catch {...} という構文は Java で基本となる構文である. 通常,何も問題がなければ try の中の文を実行してプログラムが終了する. しかし,例外(exception)が生じた場合には,catch の部分が実行される. このプログラムにおける例外は,DOM パーサ(Xerces)が何らかのエラーを検出した場合に発生する. catch の部分では,例外発生時の後始末などを書くことになるが,このプログラムでは,printStackTrace() を呼ぶことで,実行状況のスタックを表示している. プログラムの本体では,まず8行目で DOMParser オブジェクトを生成する. 10行目では,生成したパーサにより,第1引数で与えられた XML ファイルをパース(構文解析)する. この時点で XML が整形式(well-formed)であるかをチェックし,メモリ上にXML データに対する DOM の木構造を作成する. 12行目の getDocument() により,構築した木構造のルートとなるDocument オブジェクトを得る.
上記プログラムに,整形式の XML データと,(終了タグ等を省略するなどして作成した)整形式でない XML データを入力し,何が起こるか確かめてみよう.
なお,関連するソースファイルは,これまでと同様 /home/lab/Denjo/amagasa/jikken/07 においてあるので,各自のディレクトリにコピーした上で使用すること.
上に示したプログラムでは,パーサがエラーを検出した場合には,例外をcatch 文内で処理していた.しかし,エラーハンドラを用いてよりきめ細かいエラー処理を行うことが可能である. エラーハンドラによるエラー処理を含めたプログラムを以下に示す.
1: import org.w3c.dom.*; 2: import org.apache.xerces.parsers.*; 3: import org.xml.sax.*; 4: 5: class DomParserDemo2 { 6: public static void main(String[] args) { 7: try { 8: // DOM パーサの生成 9: DOMParser parser = new DOMParser(); 10: // エラーハンドラの登録 11: parser.setErrorHandler(new MyHandler()); 12: // XML 文書の取得 13: parser.parse(args[0]); 14: // Document インスタンスの取得 15: Document doc = parser.getDocument(); 16: } catch (Exception e) { 17: e.printStackTrace(); 18: } 19: } 20: } 21: 22: class MyHandler implements ErrorHandler { 23: public void warning(SAXParseException e) { 24: System.out.println("警告: " + e.getLineNumber() + "行目"); 25: System.out.println(e.getMessage()); 26: } 27: public void error(SAXParseException e) { 28: System.out.println("エラー: " + e.getLineNumber() + "行目"); 29: System.out.println(e.getMessage()); 30: } 31: public void fatalError(SAXParseException e) { 32: System.out.println("深刻なエラー: " + e.getLineNumber() + "行目"); 33: System.out.println(e.getMessage()); 34: } 35: }
エラーハンドラを使うには org.xml.sax.ErrorHandler というインタフェースの規定にしたがってハンドラを実装することになる. このインタフェースは,本来 SAX に対するエラー処理を規定したものであるが,DOM でも同様のエラー処理を行うため,このインタフェースを共用している. 3行目の org.xml.sax.* により, org.xml.sax.ErrorHandler のインタフェース情報をを読み込むようにしている. org.xml.sax.ErrorHandler には,以下の3つのメソッドが定義されている. どれも,引数として SAXParseException 型のオブジェクトを値にとる.
warning がもっとも軽いエラーであり,fatalError がもっとも深刻なエラーに対応する. プログラム本体部の違いは,11行目で MyHandler というエラーハンドラを登録している点のみである. そのエラーハンドラの実体は22〜35行目にある.それぞれのエラーの種類に応じてメソッドが定義されている.この場合はほとんど内容が同じであるが,この内容を場合に合わせて加工することで,きめ細かなエラー処理が可能となる.
上記プログラムに,意図的にエラーを起こすような XML データを入力し,何が起こるか確かめてみよう.
Xerces の DOM パーサはデフォルトでは妥当性の検証(DTD に XML 文書がしたがっているかどうかのチェック)は行わない.したがって DomParserDemo2.java で発生する例外は,
というような場合に限られる.
妥当性検証を行いたい場合には,以下のようにプログラムを修正すればよい.
1: import org.w3c.dom.*; 2: import org.apache.xerces.parsers.*; 3: import org.xml.sax.*; 4: 5: class DomParserDemo3 { 6: public static void main(String[] args) { 7: try { 8: // DOM パーサの生成 9: DOMParser parser = new DOMParser(); 10: // エラーハンドラの登録 11: parser.setErrorHandler(new MyHandler()); 12: // 妥当性検証の設定 13: parser.setFeature("http://xml.org/sax/features/validation", true); 14: // XML 文書の取得 15: parser.parse(args[0]); 16: // Document インスタンスの取得 17: Document doc = parser.getDocument(); 18: } catch (Exception e) { 19: e.printStackTrace(); 20: } 21: } 22: } 23: 24: class MyHandler implements ErrorHandler { 25: // 先の例と同じなので省略 26: }
具体的には,13行目で妥当性検証を行うフィーチャを true に設定することで, 妥当性検証を行うことを指示する. このようなXerces のフィーチャには他にも種類がある. 代表的なフィーチャは以下の通りである.
上記プログラムに,意図的にエラーを起こすような XML データを入力し,正しくフィーチャーが認識され,XML プロセッサの動作が変わったかどうかを確かめよう.
提出期限は 1/17(火).メールの作成には以下のテンプレートを利用すると良い.