第5回 2007年5月25日 「XMLパーサ」-- Java でXMLを処理 javax.xml.stream パッケージのパーサ イベントの種類の調べる 空白文字のチェック 属性の処理 応用(1) – テーブルの利用 「要素の出現回数を調べる」 java.util.Map, java.util.Set javax.xml.stream の処理の応用(2) フィルタ的な処理 MS Office 2007 のXMLを解析する java.util.Collection のフレームワーク Set, HashSet, SortedSet Map, HashMap, TreeMap javax.xml.stream XMLEventReader インタフェース XMLInputFactory クラス javax.xml.stream.events XMLEvent インタフェース サブインタフェース群 StartDocument, EndDocument, StartElement, EndElement, Characters XMLEventReader インタフェース 構文解析を実行(つまりパーサ) java.util.Iterator として扱える =発見した要素などの構成要素の集まり (つまり、処理結果のデータでもある) hasNext()メソッド、 next()メソッド nextEvent()メソッド <doc><title>ABC</title></doc> XMLInputFactory クラス XMLEventReader のインスタンスを得るた めの専用のクラス =それ自身は処理を実行するわけではない 会社の「受付係」、「案内係」の役割 XMLInputFactory factory = XMLInputFactory.newInstance(); XMLEventReader reader = factory.createXMLEventReader( source ); Factoryクラスはまず自分のインスタンス を作る Factoryのインスタンスから実際に処理を 行うインスタンスを得る XMLEventReader reader = …..; while( reader.hasNext() ) { XMLEvent event = reader.nextEvent(); System.out.println( event ); } <doc><title>ABC</title></doc> XMLEventReader がかかえるデータ javax.xml.stream.events パッケージが提供 XMLEvent が共通のスーパインタフェース StartDocument, EndDocument StartElement, EndElement Characters, Comment Attribute など <doc><title>ABC</title></doc> 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(); System.out.println( "Event " + count + ":" + event ); count++; } sample1.xml <document> <title>Java and XML</title> Let's begin, now! </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 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(); return "Start Document:version=" + version; } Characters テキストの内容 getData() 改行・空白のみかの判定 isWhiteSpace() if( event.isCharacters() ) { String data=""; if( ((Characters)event).isWhiteSpace() ) data = "White Space"; else data = ((Characters)event).getData(); return "Text:" + data; StartElement 要素の名前 getName() 開始タグ内の属性リスト getAttributes() 属性を持つ要素の例 <image source="java.png" height="400" > </image> 後で必要になる情報を記憶する(テーブルに) 複数のデータを記憶 java.util.Collection, java.util.List, java.util.Set 複数のペアのデータの表 java.util.Map (キーと値、キー全体は Set ) 値 キー • • • • <document> <tytle> <image> <text> • • • • 1 1 2 4 変数ではなく Mapを用意 Map<String,Integer> map = new HashMap<String,Integer>(); while( reader.hasNext() ) { XMLEvent event = reader.nextEvent(); if( event.isStartElement() ) { String name = ((StartElement)event) .getName().toString(); saveToTable( name, map ); } Mapへの格納方法 // 既に格納されている時ー 値を1増やす if( map.containsKey( name ) ) { Integer i = map.get( name ); map.put( name, new Integer( i+1 ) ); } // 格納されていないー新たに値1で格納 else { map.put( name, new Integer( 1 ) ); } Mapに記憶された値の利用 Set<String> keys = map.keySet(); Iterator<String> it = keys.iterator(); while( it.hasNext() ) { String key = it.next(); Integer value = map.get( key ); System.out.println( key + "=" + value ); } Collection の処理を簡潔に記述 Set<String> keys = map.keySet(); for( String key : keys ) { Integer value = map.get( key ); System.out.println( key + "=" + value ); } カウンタ変数、Iterator は表に出ない 「フィルタ」とは? 与えられた入力内容を変換して出力 入力=>[処理内容]=>出力 例: 一部分の取り出し 並べ替え 特定のパターンの検出 特定のパターンの変換 平文のテキスト部分を取り出す 特定の名前の要素を取り出す 特定の名前の要素名を変換する Characters のイベントを処理 getData()メソッドで内容を取り出す if( event.isCharacters() ) { Characters chars = (Characters)event; if( !chars.isWhiteSpace() ) { String text = chars.getData(); System.out.println( text ); } 対象はあらかじめテーブルに記憶 Map<String,String> map = new TreeMap<String,String>(); map.put( "document" , "body" ); map.put( "title" , "h1" ); map.put( ":text" , "p" ); startElement, endElementを処理 getName() メソッドでチェック StartElement se; String name = se.getName().toString(); if( map.containsKey( name ) ) { String value = map.get( name ); System.out.println( "<" + value + ">" ); } 処理をメソッドに分割する工夫 XMLEvent event = reader.nextEvent(); if( event.isStartElement() ) { startElement( (StartElement)event ); } else if( event.isEndElement() ) { endElement( (EndElement)event ); } : 要素などの名前の衝突を避ける工夫 「名前空間(Namespace)」=「住所」 URN,URI で表現 xmlns:ns=http://w3.org/Namespace 「省略形」として「プレフィックス」 xmlns:v="urn:schemas-microsoftcom:vml" : <v:ab> abcd </v:ab> javax.namespace.Qname クラス 正式なURIを含む情報を定められた形 式で記憶 getLocalPart() -- 名前空間を含まない 部分の名前 getPrefix() – 文書内のプレフィックス の名前 MicroSoft Office 2007 からファイルの 保存形式の標準は XML 複数の XMLを ZIP形式で保存 word -+- document.xml +- fontTable.xml +- settings.xml +- styles.xml +- WebSettings.xml Jar ( Java Archive ) ファイルの保存形式はZIPを採用 t オプション – 内容を調べる x オプション – 実際に展開 使用例) jar tvf Java.docx jar xvf Java.docx ZIP形式のファイルを直接処理する ZipFile クラス – ZIP形式のファイル ZipEntry クラス – 格納された個々の ファイルやディレクトリ ZipEntry の集まりは java.util.Enumeration (古いスタイルだが、取り扱いは java.util.Iterator とほぼ同じ)
© Copyright 2025 ExpyDoc