第3回 2007年4月27日 応用Java (Java/XML)
この講義の目的(再確認) JavaのアプリケーションでXMLを処理するには? サーバサイドの開発の基礎 Webサービス エンタープライズ・アプリケーション
前回までやったこと なぜ Javaと XML か? Java SE 6 の XML 関連のAPI 「XMLパーサ」とは? javax.xml.stream パッケージのパーサ XMLEventReader と XMLInputFactory (「Factory のデザインパターン」) XMLEventReader と java.util.Iterator javax.xml.stream.events の XMLEvent
本日(4/27)の講義内容 javax.xml.stream による処理(続き) XMLEvent から詳しい情報を取り出す 属性( Attribute ) を処理するには?
(復習1) XMLパーサとは? XML文書内の字句を解析 要素、属性などの情報を取り出す (アプリケーションが1文字ずつの処理を行う必要はない) <doc> <title> Java and XML </title> <image source=“jax.png” /> </doc>
(復習2) XMLパーサの種類 標準のクラスライブラリで提供 (新しくパーサを設計する必要なし) 複数の種類(標準的な処理パターン) SAX(Simple API for XML) DOM(Document Object Model) javax.xml.streamパッケージ
(復習3) パッケージとAPI javax.xml.stream XMLEventReader インタフェース XMLInputFactory クラス javax.xml.stream.events XMLEvent インタフェース サブインタフェース群 StartDocument, EndDocument, StartElement, EndElement, Characters
javax.xml.stream のAPI(1) XMLEventReader インタフェース 構文解析を実行(つまりパーサ) java.util.Iterator として扱える =発見した要素などの構成要素の集まり (つまり、処理結果のデータでもある) hasNext()メソッド、 next()メソッド nextEvent()メソッド <doc><title>ABC</title></doc>
javax.xml.stream のAPI(2) XMLInputFactory クラス XMLEventReader のインスタンスを得るための専用のクラス =それ自身は処理を実行するわけではない 会社の「受付係」、「案内係」の役割
Factory の「デザインパターン」 XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader reader = factory.createXMLEventReader( source ); Factoryクラスはまず自分のインスタンスを作る Factoryのインスタンスから実際に処理を行うインスタンスを得る
なぜ Factory のパターンか? 「実装クラス」の実体を隠す(なぜ?) XMLEventReader reader = new XMLEventReader( source ); とはしない XMLEventReader はインタフェース(抽象化) 実装クラスを交換可能 実行環境によって実装クラスが異なる場合にも柔軟に対応
必要なデータの取り出し方 XMLEventReader reader = …..; while( reader.hasNext() ) { XMLEvent event = reader.nextEvent(); System.out.println( event ); } <doc><title>ABC</title></doc>
XMLEvent とその仲間たち XMLEventReader がかかえるデータ javax.xml.stream.events パッケージが提供 XMLEvent が共通のスーパインタフェース StartDocument, EndDocument StartElement, EndElement Characters, Comment Attribute など <doc><title>ABC</title></doc>
XMLEvent の種類の判定 XMLEvent インタフェースに定義された定数 XMLEvent.START_ELEMENT 等 XMLEvent の getEventType() メソッドの返値 使用例) XMLEvent event = reader.nextEvent(); if( event.getEventType() == XMLEvent.START_ELEMENT ) { :
javax.xml.stream のまとめ XMLInputFactory が自身のデータを作る XMLEventReder が Factoryから得られる その時点で既に処理されたデータと考えて処理できる(=複数のXMLEvent ) hasNext() メソッドと nextEvent()メソッド ループの中で1個ずつイベントを処理 イベントの種類は XMLEvent の定数値で場合分け
前回の実習の解説(1-1) import javax.xml.stream.events.*; 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 ) {
前回の実習の解説(1-2) try { StreamSource source = new StreamSource( args[0] ); XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader reader = factory.createXMLEventReader( source );
前回の実習の解説(1-3) int count=0; while( reader.hasNext() ) { XMLEvent event = reader.nextEvent(); System.out.println( "Event " + count + ":" + event ); count++; }
前回の実習の解説(1-4) sample1.xml <document> <title>Java and XML</title> Let's begin, now! </document>
前回の実習の解説(1-5) 予想される出力結果? Event 0: <document> Event 1: <title> Event 2: Java and XML Event 3: </title> Event 4: Let's begin, now! Event 5: </document>
実際の実行結果 Event 0: <?xml version=“1.0” encoding=“UTF-8” ?> Event 1: <document> Event 2: Event 3:<title> Event 4: Java and XML Event 5: </title> Event 6: Let’s begin, new! Event 7: </document> Event 8: ENDDCUMENT
予想されなかったイベント Event 0: 文書の開始 (StartDocument) XML文書の性質についての情報 version, encoding, standalone Event 2: 改行文字(Characters) 人間に見やすくするだけのものだが コンピュータにとってはテキスト Event 8: 文書の終了(EndDocument)
他のXML文書のテキスト(1) sample2.xml <?xml version="1.0" encoding="UTF-8"?> <!-- This is a comment. --> <document> <title>Java and XML</title> Let's begin, now! </document>
他のXML文書のテキスト(1) sample2.xml Event 0:<?xml version="1.0" encoding="UTF-8"?> Event 1:<!-- This is a comment. --> Event 2:<document> Event 3: Event 4:<title> Event 5:Java and XML Event 6:</title> Event 7:Let's begin, now! Event 8:</document> Event 9:ENDDOCUMENT
他のXML文書のテキスト(2) sample3.xml <document> <title> Java and XML</title> Let's begin, now! <image source="java.png" height="40" width="50"/> <!-- <image source="java.png" height="400"/> --> </document>
他のXML文書のテキスト(2) sample3.xml <document> Event 2: <title> Event 4:Java and XML</title> Event 6:Let's begin, now! <image source="java.png" height="40" width="50"/> Event 9: <!-- <image source="java.png" height="400"/> --> Event 11: </document>
前回の実習の解説(2-1) XMLEventReaderTest2.java XMLEvent の getEventType()メソッド System.out.println( "Event " + count + ":" + event.getEventType() );
前回の実習の解説(2-2) getEventType() の返り値の型は int型 Event 0: 7 Event 1: 1
前回の実習の解説(3-1) XMLEventReaderTest3.java イベントのタイプを識別 XMLEvent event = reader.nextEvent(); int type = event.getEventType(); System.out.println( "Event " + count + ":" + typeToString( type ) );
前回の実習の解説(3-2) イベントタイプの定数値と比較 private static String typeToString( int type ) { switch( type ) { case XMLEvent.START_DOCUMENT: return "StartDocument"; : case XMLEvent.CHARACTERS: return "Caracters"; default: return "Others"; }
XMLEventの種類の判定(その2) XMLEvent に定義されたメソッド isStartElement() など boolean型の返り値 if( event.isStartDocument() ) { return "Start Document”; } else if( event.isEndDocument() ) { return "End Document"; :
各イベントごとのメソッド StartDocument sdevent; String version = sdevent.getVersion(); return "Start Document:version=" + version; if( event.isStartDocument() ) { String version = ((StartDocument)event).getVersion(); }
各イベントごとのメソッド(2) Characters テキストの内容 getData() 改行・空白のみかの判定 isWhiteSpace() if( event.isCharacters() ) { String data=""; if( ((Characters)event).isWhiteSpace() ) data = "White Space"; else data = ((Characters)event).getData(); return "Text:" + data;
各イベントごとのメソッド(3) StartElement 要素の名前 getName() 開始タグ内の属性リスト getAttributes() 属性を持つ要素の例 <image source="java.png" height="400" > </image>
属性の処理の方法(1) 属性 Attribute も XMLEvent Attributeは StartElementの内部に存在 (XMLEventReaderから直接取り出せない) Attribute の個数・順序は任意 再度 java.util.Iterator が登場
属性の処理の方法(2) java.util.Iterator 複数のデータを1個ずつ順にたどる (配列のように「何番目」の指定はない) Iterator it; while( it.hasNext() ) { Object obj = it.next(); }
属性の処理の方法(3) Iterator からの取り出しせる型は任意 Object 型を Attribute に「キャスト」する Object obj = it.next(); Attribute attr = (Attribute)obj; Attribute 属性の名前 getName(); 属性の値 getValue();
属性の処理の方法(4) while( it.hasNext() ) { Object obj = it.next(); if( obj instanceof Attribute ) { Attribute attr = (Attribute)obj; String name = attr.getName().toString(); String value = attr.getValue(); System.out.println( name + "=" + value +); }