SAXとイベント駆動型処理

Download Report

Transcript SAXとイベント駆動型処理

第6回 2007年6月1日
「XMLパーサ」-- Java でXMLを処理
javax.xml.stream パッケージのパーサ
イベントの種類の調べる
 応用(1) – テーブルの利用
「要素の出現回数を調べる」
 応用(2) – フィルタ的な処理
java.util.Map, java.util.Set
 応用(3) – MS Office 2007 のファイルを
処理する






javax.xml.stream の処理の再設計
処理内容を複数のクラスに分ける
SAX(Simple API for XML)の処理
javax.xml.stream
XMLEventReader インタフェース
XMLInputFactory クラス
 javax.xml.stream.events
XMLEvent インタフェース
サブインタフェース群
StartDocument, EndDocument,
StartElement, EndElement, Characters

javax.xml.parsers パッケージ
SAXパーサ、DOMパーサを提供
 org.xml.sax パッケージ
 org.w3c.dom パッケージ


XMLEventReaderTest1.java
import javax.xml.stream.*;
import javax.xml.stream.events.*;
import javax.xml.transform.stream.*;
public class XMLEventReaderTest1 {
public static void main( String[] args ) {
try {
StreamSource source
= new StreamSource( args[0] );
XMLInputFactory factory
= XMLInputFactory.newInstance();
XMLEventReader reader
= factory.createXMLEventReader(
source );
int count=0;
while( reader.hasNext() ) {
XMLEvent event = reader.nextEvent();
if( event.isStartElement() ) {
((StartElement).event).getName();
:
:
}

処理をメソッドに分割する
XMLEvent event = reader.nextEvent();
if( event.isStartElement() ) {
startElement( (StartElement)event );
} else if( event.isEndElement() ) {
endElement( (EndElement)event );
}
:



文書の入力先とパーサの取得
イベントの場合分けと処理の呼び出し
各イベントごとの処理の内容



ParserTest – 文書の指定とパーサの取得
EventCase – イベントの場合分けとメソッ
ドの呼び出し
EventProc – イベントの処理の内容の記述
public class ParserTest {
public static void main( String[] ) {
try {
Source s = new StreamSource( name );
XMLInputFactory factory
= XMLInputFactory.newInstance();
XMLEventReader reader
= factory.createXMLEventReader( s );
EventCase ec = new EventCase();
ec.dispatch( reader );
public class EventCase {
public void dispatch( XMLEventReader r );
try{
EventProc proc = new EventProc();
while( r.hasNext() ) {
XMLEvent event = r.nextEvent();
if( event.isStartElement() ) {
proc.startElement();
}
:
public class EventProc {
public void startElement( StartElement se) {
:
}
public void endElement( EndElement ee ) {
:
}
public void characters ( Characters ch ) {
:
}




イベントの場合分けはいつも同じ
表に出なくてもいいのでは?
1つの方法:「クラスの継承」
AbstractEventProcessor クラス
イベントの場合分けと呼び出しを記述
EventProcessorクラス
処理の内容の記述
public class EventProcessor
extends AbstractEventProcessor {

インタフェースの導入
メソッドの名前、型を常に同じに制約
public interface EventProcessorIF {
public void startElement( StartElement es);
public void endElement( EndElement ee );
public void characters( Characters ch );
:
}
public abstract class AbstractEventProcessor
implements EventProcessorIF {
public void process ( XMLEventReader r ) {
while( r.hasNext() ) {
XMLEvent event = r.nextEvent();
if( event.isStartElement( ) ) {
startElement( (StartElement)event) ;
}
:
}
public abstract void startElement(StartEement se );



javax.xml.parsers
最も初期から利用可能だったパーサ
目的、設計は「今回の工夫」と共通
最も抽象化されたレベル(JAXP)
 パーサを「取り出す」ための仕組みを
提供
 SAXParser,
SAXParserFactory
DocumentBuilder,
DocumentBuilderFactory
 唯一の手段ではないが、「標準」を提
供

SAXParserFactory spf =
SAXParserFactory.newInstance();
SAXParser parser =
spf.newSAXParser();
XMLReader reader =
parser.getXMLReader();
XMLInputFactory factory =
XMLInputFactory.newInstance();
XMLEventReader reader =
factory.createXMLEventReader( source );


Factoryクラスはまず自分のインスタンス
を作る
Factoryのインスタンスから実際に処理を
行うインスタンスを得る
XML文書を読み込みながら処理
 特定の「節目」でイベントが発生
(イベント駆動型の処理)
 イベントの処理はHandlerが担当
ContentHandler(のサブクラス)
ErrorHandler(のサブクラス)

XMLReader reader =
parser.getXMLReader();
reader.setContentHandler(
new MyContentHandler() );
reader.setErrorHandler(
new MyErrorHandler() );
XMLReader reader ….
:
InputSource source =
new InputSource( “sample.xml” );
reader.parse( source );
XML文書の読み込みと処理が並行に進行
 要素(タグ)ごとに逐次処理
 読み込みと処理は同時に終了
(後処理には別の機構が必要)






startDocument() – パーシングの開始時
endDocument() – パーシングの終了時
startElement() – 要素(タグ)の開始
endElement() – 要素(タグ)の終了
characters() – 平文テキストの読み込み
名前空間の処理
 妥当性の検証とWhite Spaceの処理
*以上は次回以降に利用

3つのエラーレベル
fatalError
文書名の間違い、不存在
XML文書として不適切(文法エラー)
 error
XML文書の設計に不適合(非妥当性)
 warning
エラーではない不適切な記述

