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
エラーではない不適切な記述