2011-12-9作成

 ■SAXを使ってXMLデータにアクセスしてみる

 ■SAXによるXML解析

 ここでは前ページで説明した事例

クライアントにWindows.NETアプリを使用した構成

の中で、クライアントからの要求を受け付けるサーブレット部分の説明をします。ここでクライアントからの要求(XML)をSAXを利用して解析しています。

SAXによるXML解析の概要

 最初にSAXによるXML解析の概要を図示します。なおこの概念図はXML文書全体をStringとして保持している場合に有効です。XML文書がファイルの場合などは図の左下の構成が少し変わってきます。

SAX利用の概念図

 ここの手順は

  1. SAXParserFactoryからSAXParserを生成
  2. XML全体をStringオブジェクトとして保持
  3. そのXMLを保持しているStringをStringReaderに設定
  4. そのStringReaderInputSourceに設定
  5. XML解析結果からデータ保持クラスを生成するハンドラークラスを自前で作成
  6. InputSourceクラスと自前のハンドラークラスを引数にして、SAXParserparseメソッドを実行
  7. ハンドラークラス(DefaultHandlerクラスを継承したもの)から結果のデータ保持クラスを取得
といった流れです。

 ここで出てくるクラスのコンストラクタやメソッドについて、簡単に触れておきます。StringReaderなどは知っておいて損は無いのですが、その他については使用する上で最小限の説明となります。

 StringReader

 ここで説明するSAXの使い方ではStringReaderクラスが出てきます。出てくるだけでここではこれのメソッドは使いません。ですが文字列を扱うときにこれを介することによって、操作しやすい場合があるので説明しておきます。

 StringReaderのパッケージはjava.io.StringReaderです。

 ・StringReader のコンストラクタ

StringReader のコンストラクタ
コンストラクタ 引数(パラメータ)
説明
StringReader String 操作対象文字列
 指定した文字列に対する文字列リーダーを生成する。

 ・StringReader に対するメソッド

StringReaderに対する主なメソッド
メソッド 戻り値 引数(パラメータ)
説明
readyboolean
 設定した文字列から読み込み可能かを判定する。
readint
 設定した文字列の現在の位置から1文字を読み込み、その文字コード(ハッシュコード)が返る。文字列の終わりで読み込めないときは−1が返る。
 返るのはintの文字コード(ハッシュコード)なので文字として使用するときは
(char)StringReader型変数.read();
のようにchar型に変換(キャスト)する。
char[] 格納先文字配列 , int 格納位置 , int 読み込み文字数
 設定した文字列の現在の位置から指定した文字数分の文字を読み込み、指定した文字配列の指定位置に格納する。
 戻り値として実際に読み込まれて文字配列に格納された文字数が返る。
指定文字数 ≦ 文字列リーダーの残り文字数のときは指定文字数
指定文字数 > 文字列リーダーの残り文字数のときは残り文字数
が戻り値となる。
 文字列の終わりに達していたときは−1が返る。
skiplong long 読み飛ばし文字数
 現在の読み取り位置から指定した文字数分だけ読み飛ばす。
 戻り値として実際に読み飛ばしが行われた文字数が返る。
markSupporttedboolean
 この文字列リーダーがmark操作可能かを判定する。
markvoid int マーク保持上限文字数
 現在の読み取り位置にマーク付けを行う。先に読み進んだ後も、resetを発行することによりこの位置に戻ることが出来る。
 引数として設定したマーク位置を保持したまま読み込める文字数の上限を指定出来る。元の文字列から読み込まれるため実際の上限は無いので、正の値を指定しておけばよい。
resetvoid
 読み込み位置をマーク付けした場所に戻す。マーク付けされていない場合は文字列の先頭に戻す。
closevoid
 文字列リーダーを閉じる。

 InputSource

 InputSourceクラスを直接使う状況は、私の経験内ではありませんでした。ここでは必要最小限ということでコンストラクタの説明だけを書いておきます。

 InputSourceのパッケージはorg.xml.sax.InputSourceです。

 ・InputSource のコンストラクタ

InputSource のコンストラクタ
コンストラクタ 引数(パラメータ)
説明
StringReader
 引数無しのデフォルトコンストラクタ。後からsetByteStreamsetCharacterStreamsetPublicIdsetSystemIdといったセッター系メソッドで入力ソースを指定する。
InputStream バイトストリーム
 バイトストリームを指定して新しい入力ソースを作成する。
Reader 文字ストリーム
 文字ストリームを指定して新しい入力ソースを作成する。
 文字ストリームとしてStringReaderFileReaderを指定すればよい。本サイトではStringReaderを使用した例で説明する。
String システム識別子
 システム識別子を指定して新しい入力ソースを作成する。

 SAXParserFactory

 XMLをSAXで解析するためのSAXParserクラスを生成するために使います。

 SAXParserFactoryのパッケージはjavax.xml.parsers.SAXParserFactoryです。

 ・SAXParserFactory のコンストラクタ

 SAXParserFactoryのコンストラクタはprotectedになっており、使うことはありません。staticで定義されているnewInstanceを使います。

 ・SAXParserFactory に対するメソッド

SAXParserFactoryに対する主なメソッド
メソッド 戻り値 引数(パラメータ)
説明
newInstanceSAXParserFactory
 新しいSAXParserFactoryを生成する。
newSAXParserSAXParser
 現在設定されているSAXParserFactoryから新しいSAXParserを生成する。
setNamespaceAwarevoid boolean
 生成したSAXParserが、XML名前空間をサポートするか否かを指定する。デフォルトはfalse、サポートさせる場合はtrue、させない場合はfalseを指定する。
setValidatingvoid boolean
 生成したSAXParserが、構文解析時にドキュメントを検証するか否かを指定する。デフォルトはfalse、サポートさせる場合はtrue、させない場合はfalseを指定する。

 SAXParser

 XMLをSAXで解析するためのクラスです。解析時に自作のハンドラークラスを登録しておきます。

 XML解析を実行してXMLタグやデータが見つかる度、ハンドラークラスのメソッドがSAXParserから呼び出されます。

 またSAXParserはスレッドセーフではありません。あるSAXParserインスタンスが複数のスレッドから同時に使用された場合、動作は保証されません。アプリ側でスレッドセーフな実装にしておく必要があります。

 SAXParserのパッケージはjavax.xml.parsers.SAXParserです。

 ・SAXParser のコンストラクタ

 SAXParserのコンストラクタはprotectedになっており、使うことはありません。SAXParserFactorynewSAXParserメソッドで生成します。

 ・SAXParser に対する主なメソッド

 この後に例示するサンプルで使用するものを説明します。

SAXParserに対する主なメソッド
メソッド 戻り値 引数(パラメータ)
説明
parsevoid InputSource 入力ソース , DefaultHandler ハンドラークラス
 指定した入力ソースの内容を、指定したハンドラークラスを使用してXMLとして構文解析する。
File 入力ファイル , DefaultHandler ハンドラークラス
 指定した入力ファイルの内容を、指定したハンドラークラスを使用してXMLとして構文解析する。

 DefaultHandler

 XMLをSAXで解析するときの、SAX2仕様におけるイベントハンドラの基底クラスです。

 アプリケーション側はこのDefaultHandlerを継承したハンドラークラスを作成しておきます。ハンドラークラスではDefaultHandlerに定義されているメソッドのうち必要なものをオーバーライドして定義します。このメソッドはSAXParserから呼び出されるので、適宜データを保持して最終的にデータ保持クラスを返せるようにすれば良いでしょう。

 DefaultHandlerのパッケージはorg.xml.sax.helpers.DefaultHandlerです。

 ここはオブジェクト指向的な説明を加えておきましょう。

 SAXParserで構文解析をするときにDefaultHandlerを継承したハンドラークラスを指定します。SAXParserでは構文解析でイベントが発生したときに、DefaultHandlerで定義しているメソッドを呼び出します。

 このときに指定したハンドラークラスの、DefaultHandlerクラスのメソッドをオーバーライドしたメソッドが呼ばれます。ハンドラークラスに未定義のものはスーパークラスであるDefaultHandlerクラスのメソッドが呼び出されるという仕組みです。

 そしてDefaultHandlerでは何もしない空メソッドとして定義されているため、指定したハンドラークラスで未定義のものはイベントが発生しても何も処理はされません。

 ・DefaultHandler のコンストラクタ

DefaultHandler のコンストラクタ
コンストラクタ 引数(パラメータ)
説明
DefaultHandler
 ハンドラークラスのデフォルトコンストラクタ。

 ・DefaultHandler に対する主なメソッド

 この後に例示するサンプルで使用するものを中心に説明します。ハンドラークラスではこの中で必要なものをオーバーライドして定義しておきます。最低限としてはサンプルでも例示しているstartElementendElementcharactersendDocumentでしょうか。

DefaultHandlerに対する主なメソッド
メソッド 戻り値 引数(パラメータ)
説明
startDocumentvoid

 文書の開始通知を受け取る。

 解析結果をファイル出力するなら初期作成をしたり解析結果のデータ保持クラスを初期化したりなど、必要な初期処理を行うことが出来る。

endDocumentvoid

 文書の終了通知を受け取る。

 解析中は内部保持していたデータから結果用データ保持クラスを作成したり、解析に使用したデータ領域の開放や終了処理などを行うことが出来る。

startElementvoid String URI , String XMLタグ名 , String 修飾名 , Attributes XML属性

 XML要素の開始通知を受け取る。

 引数としてタグ名を受け取れるので、それが想定されているものか判定できる。またタグに対するデータ用の領域確保などを行う。

charactersvoid char[] 文字 , int 開始位置 , int 文字数

 要素内の文字を受け取る。

 文字は文字配列として渡されるので、開始位置・文字数と併せて実データを取得する。例えばstartElementメソッドでStringBufferを確保し、charactersメソッドでStringBuffer.append(受けた文字配列, 受けた開始位置, 受けた文字数);としてやればよい。

endElementvoid String URI , String XMLタグ名 , String 修飾名

 XML要素の終了通知を受け取る。

 引数として受けたタグ名に対する、データの取り込みが終わったことが分かる。例えばcharactersメソッドでStringBufferに貯めたデータをtoStringで文字列として保持したり、あるいはタグに対する最終的なデータ型に変換して保持したりする。

 ■SAXによるXMLの利用法

 ここまでSAXによるXMLの利用法について概念図と関連する主なクラスとそのメソッドについて説明しました。

 しかしこれまでの説明を見てもピンと来ないとおもいます。

 そこで具体的なサンプルを元にした説明を次ページ以降でしていこうと思いますが、サンプル作成中ですのでお待ちください。






このページの先頭  JAVA編先頭1  JAVA編先頭2  サーバーJava入門先頭

Copyright © 2011 yok. All Rights Reserved.