倭マン's BLOG

くだらない日々の日記書いてます。 たまにプログラミング関連の記事書いてます。 書いてます。

XMLStreamReader

XMLStreamReader も、XMLEventReader 同様 XML 文書を解析するクラスですが、解析中に XML イベントオブジェクトを生成しないため素早く動作します。 XMLSteamReader を用いた XML 文書の解析の手順は、XMLEventReader と(解析処理の実装以外は)ほとんど同じで、以下のようになります(以前の記事参照):

  1. XMLInputFactory のインスタンスを取得する
  2. (必要なら)XMLInputFactory の設定をする
  3. XMLStreamReader のインスタンスを取得する
  4. XMLStreamReader のインスタンスを用いて XML 文書の解析を行う
  5. XMLStreamReader を閉じる

簡単なサンプルは次のようになります(引数の java.io.Reader オブジェクトから解析対象の XML 文書を読み込みます):

public void analyze(Reader input)throws XMLStreamException{
    // 1. XMLInputFactory のインスタンスを取得する
    XMLInputFactory factory = XMLInputFactory.newInstance();
        
    // 2. (必要なら)XMLInputFactory の設定をする
    factory.setProperty(XMLInputFactory.IS_NAMESPACE_AWARE, true);
        
    XMLStreamReader reader = null; 
    try{
        // 3. XMLStreamReader のインスタンスを取得する
        reader = factory.createXMLStreamReader(input);
            
        // 4.  XML 文書の解析を行う
        while(reader.hasNext()){
            // ここで各 XML イベントに対する処理を行う
        }
            
    }finally{
        // 5. XMLStreamReader を閉じる
        if(reader != null)
            reader.close();
    }
}

各ステップについて少し詳しく見ていきましょう。

XMLInputFactory のインスタンスを取得する、設定をする


XMLEventReader の場合と全く同じなので省略します。

XMLStreamReader のインスタンスを取得する


XMLStreamReader のインスタンスは XMLInputFactory のメソッド XMLInputFactory#createXMLStreamReader() によって生成します。

XMLStreamReader reader = factory.createXMLStreamReader(input);

createXMLStreamReader() メソッドに渡せるオブジェクトのうち、解析対象の XML 文書を指定するものは次の3つです:

  • java.io.InputStream
  • java.io.Reader
  • javax.xml.transform.Source

これらのオブジェクトに加えて、createXMLEventReader() メソッド同様、エンコーディング(InputStream の場合)やシステム識別子(InputStream, Reader の場合)を指定する文字列も渡すことができます。

XML 文書の解析を行う


XMLStreamReader の使い方は XMLEventReader と同名のメソッドがありますが、XML イベントのようなオブジェクトは返しません。 next() メソッドや nextTag() メソッドを呼び出すと、XMLStreamReader 自体の状態が変わります。 XML 文書の解析時に要素名やテキストの内容を取得したい場合は、XMLStreamReader に定義されている getter メソッドなどを呼び出します。

状態遷移に関連するメソッド

XMLStreamReader の状態遷移は状態の確認に使用するメソッドには以下のようなものがあります:

メソッド名 備考
hasNext() 次の XML イベントがあるかどうかを判定します。
next() XMLStreamReader の状態を次の XML イベントに遷移させます。
nextTag() XMLStreamReader の状態を次の開始タグまたは終了タグまで遷移させます。
require() XMLStreamReader の現在の状態が指定されたものに一致するかどうかを判定します。

XML ノードの情報を取得するメソッド

XMLStreamReader の各状態に対して、XML ノードの情報を取得するメソッドが多数定義されています。 基本的には XML イベントに定義されているメソッドと同じですが、それらが XMLStreamReader 自身に定義されている事に注意しましょう。

XMLStreamReader の状態 情報取得メソッド
START_DOCUMENT getEncoding(), getVersion(), isStandalone(), standaloneSet(), getCharacterEncodingScheme()
START_ELEMENT getName(), getLocalName(), hasName(), getPrefix(), getAttributeXxx(), isAttributeSpecified(), getNamespaceXxx(), getElementText()
END_ELEMENT getName(), getLocalName(), hasName(), getPrefix(), getNamespaceXxx()
CHARACTERS getTextXxx()
CDATA getTextXxx()
SPACE getTextXxx()
COMMENT getTextXxx()
PROCESSING_INSTRUCTION getPITarget(), getPIData()
ENTITY_REFERENCE getLocalName(), getText()
DTD getText()
  • getNamespaceXxx() には getNamespaceContext(), getNamespaceCount(), getNamespacePrefix(), getNamespaceURI() があります。
  • getAttributeXxx() には getAttributeCount(), getAttributeName(), getAttributePrefix(), getAttributeNamespace(), getAttributeLocalName(), getAttributeType(), getAttributeValue() があります。
  • getTextXxx() には getText(), getTextCharacters(), getStart(), getLength() があります。

プロパティ風 XML ファイルの解析

XMLEventReader 同様、nextTag() や getElementText() は、プロパティ風の XML ファイルに対して用いることができます。 次のような XML ファイルがあったとしましょう:

<book>
  <title>イラスト西洋哲学史下</title>
  <author>小阪修平</author>
  <price>610</price>
  <isbn>978-4-7966-6598</isbn>
</book>

この XML ファイルを解析して、プロパティを表示する簡単なサンプルコードは例えば次のようになります:

public void iterateProperties()throws Exception{

    XMLInputFactory factory = XMLInputFactory.newInstance();
    XMLStreamReader reader = factory.createXMLStreamReader(new FileReader("book.xml"));
        
    // <book> 要素まで処理を飛ばす
    reader.nextTag();
            
    while (reader.hasNext()) {
        // 次のタグへ状態を遷移
        reader.nextTag();

        // 終了タグの場合はループから抜ける
        if(reader.isEndElement())
            break;
                
        // 要素名と子テキストを表示
        System.out.println(start.getName()+"="+reader.getElementText());
    }
            
    reader.close();
}

getElementText() メソッドを呼び出した後、XMLStreamReader の状態は要素下のテキストの次の終了要素に移るのに注意しましょう。

これを実行すると次のように表示されます:

title=イラスト西洋哲学史下
author=小阪修平
price=610
isbn=978-4-7966-6598

XMLEventReader を閉じる


XMLEventReader の場合と同じなので省略します。