連載
» 2001年06月16日 00時00分 公開

Javaで実現するDOM/SAXプログラミング(5):階層構造を持つXML文書をSAXで処理する (2/4)

[太田一郎,ティアイエス株式会社]

SAXで設定ファイルを読み込む

 以前、DOMの応用例として、設定ファイルをXMLで記述し、それを読み込むというサンプルを取り上げました。その際、設定情報としてはリスト1のようなJDBCの接続設定を用いました。

<?xml version="1.0" encoding="UTF-8"?>
       
<connection id="識別子">
  <url>接続先DBのURL</url>
  <driver>ドライバのクラス名</driver>
  <user>ユーザー名</user>
  <password>パスワード</password>
  <property name="プロパティの値" value="プロパティの値" />
</connection>
リスト1 JDBCの接続設定をXMLで記述するサンプル(jdbc_sample.xml

 見れば簡単に分かると思われますので、この設定情報に関するおさらいは省きますが、必要であれば前々回の「DOMプログラムの実例」を参照してください。最初は小手調べも兼ねて、この例をSAXで処理することに挑戦してみます。

 前回の「SAXによるシンプルなXML文書の操作」で説明したとおり、SAXでのプログラミングは大きく分けると以下のような流れになります。

  • コンテントハンドラの作成
  • パーサファクトリおよびパーサの生成
  • 構文解析処理の呼び出し

 コンテントハンドラの作成以外は毎回ほぼ決まった形になりますから、以下ではコンテントハンドラの作成を中心に見ていくことにしましょう。

 コンテントハンドラのプログラミングで難しいのは、構文解析の過程で逐次発生するイベントをどのように関連付けるかというところです。

 例えば、JDBCの接続設定でURLを設定しているところに注目してください。

<url>接続先URL</url>

 開始タグ、URLのテキスト、終了タグを読み込んだところでそれぞれSAXのイベントが発生します。ここで、読み込んだテキストがURLタグの情報だということを認識するところがプログラミングのポイントになります。

 このイベントの関連付けを処理するにはいくつかのやり方が考えられますが、取りあえずは一番簡単なパターンを用いてみます(リスト2)。

import org.xml.sax.*;
import org.xml.sax.helpers.*;
import java.util.*;
   
public class ConfigHandler extends DefaultHandler {
   
    /** JDBCドライバ名. */
    private String driver;
   
    /** JDBCの接続先URL. */
    private String url;
   
    /** JDBCの接続先ユーザ. */
    private String user;
   
    /** JDBCの接続用パスワード. */
    private String password;
   
    /** JDBCの接続用プロパティ. */
    private Properties props;
   
    /** テキストデータの一時読み込み用バッファ. */
    private String text;
   
    public void startDocument() {
        driver   = null;
        url      = null;
        user     = null;
        password = null;
        props    = new Properties();
    }
     
    /**
     * 開始タグの処理.
     * propertyタグのみ処理.
     */
    public void startElement(String namespaceURI,
                             String localName,
                             String qName,
                             Attributes atts) {
     
        if (qName.equals("property")) {
            String name  = atts.getValue("name");
            String value = atts.getValue("value");
            props.setProperty(name, value);
        }
    }
   
    /**
     * 終了タグの処理.
     * propertyタグ以外はここで値をセット.
     */
    public void endElement(String namespaceURI,
                           String localName,
                           String qName) {
 
        if (qName.equals("driver")) {
            driver = text;
        } else if (qName.equals("url")) {
            url = text;
        } else if (qName.equals("user")) {
            user = text;
        } else if (qName.equals("password")) {
            password = text;
        }
    }
   
    public void characters(char[] ch, int start, int length) {
         text = new String(ch, start, length);
    }
}
リスト2 JDBCの接続設定を読み込むためのコンテントハンドラ(ConfigHandler.java

 見ればお分かりになるように、非常に単純なアプローチをとっています。テキストのイベントが発生したら、その内容をバッファ変数textにいったん記憶しておき、終了タグを読み込んだところで、タグに対応する変数にコピーしています。

 少しだけ取り扱いが異なるのが、propertyタグの情報です。propertyタグの情報は属性として与えられていますので、ほかのタグのように一度バッファに読み込む手間は不要です。リスト2を見れば分かるように、開始タグを読み込んだ時点でその属性を取り出しています。

 ここでは省いていますが、実際に使用するならば、driverやuserにセットされた値を取り出すためのアクセサが必要です。皆さんが試される場合には各自で適宜補ってみてください。

 次はもう少し複雑な例を見てみることにしましょう。

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。