倭マン's BLOG

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

6. StAX とのブリッジ

前回は SAX とのブリッジ、というか SAX の成果物の再利用方法を見ました。 今回は、StAXAPI を使用する方法を考えます。

SAX では処理の実装はほとんど org.xml.sax.ContentHandler などのコールバック・クラス(XxxxHandler クラス)に定義されているので、それを使い回すのは簡単でしたが、StAX を用いて開発された処理の実装はイマイチ使い回し方が分からないので、今回扱うのは

  • javax.xml.stream.XMLStreamReader, javax.xml.stream.XMLEventReader から読み込む
  • javax.xml.stream.XMLStreamWriter へ書き出す

の2点にします。

javax.xml.stream.XMLStreamReader, javax.xml.stream.XMLEventReader から読み込む


これは特に新しくクラスなどを作成する必要はなく、javax.xml.transform.stax.StAXSource クラスを使用するだけで OK です:

import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.Source;
import javax.xml.transform.stax.StAXSource

public void parse(XMLStreamWriter writer){
    Source src = new StAXSource(writer);
    ...
}

javax.xml.stream.XMLStreamWriter へ書き出す


javax.xml.stream.XMLStreamWriter へ XML 文書を書き出す処理を考えましょう。 
javax.xml.stream.XMLStreamWriter は StAXAPI ですが、プッシュ・パースに使用する XMLEventHandler クラスを使用してこの処理を実装します。 まず XMLEventHandler のサブクラス:

package xmlparsing.stax;

import java.io.*;
import javax.xml.stream.*;
import javax.xml.transform.Result;

import xmlparsing.XMLEventHandler;
import xmlparsing.events.*;

public class StaxEventWriterHandler implements XMLEventHandler {
    
    private static XMLOutputFactory FACTORY = XMLOutputFactory.newInstance();
    
    private final XMLStreamWriter writer;
    
    public StaxEventWriterHandler(OutputStream os)throws XMLStreamException{
        this(FACTORY.createXMLStreamWriter(os));
    }
    
    public StaxEventWriterHandler(Writer writer)throws XMLStreamException{
        this(FACTORY.createXMLStreamWriter(writer));
    }
    
    public StaxEventWriterHandler(Result result)throws XMLStreamException{
        this(FACTORY.createXMLStreamWriter(result));
    }
    
    public StaxEventWriterHandler(XMLStreamWriter writer){
        this.writer = writer;
    }

    public void startDocument(StartDocument event) {
        try{
            this.writer.writeStartDocument();
            
        }catch(XMLStreamException ex){
            throw new RuntimeException(ex);
        }
    }

    public void endDocument(EndDocument event) {
        try{
            this.writer.close();
            
        }catch(XMLStreamException ex){
            throw new RuntimeException(ex);
        }
    }

    public void startElement(StartElement event) {
        try{
            this.writer.writeStartElement(event.getName());
            
        }catch(XMLStreamException ex){
            throw new RuntimeException(ex);
        }
    }

    public void endElement(EndElement event) {
        try{
            this.writer.writeEndElement();
            
        }catch(XMLStreamException ex){
            throw new RuntimeException(ex);
        }
    }

    public void text(Text event) {
        try{
            this.writer.writeCharacters(event.getText());
            
        }catch(XMLStreamException ex){
            throw new RuntimeException(ex);
        }
    }
}

これを使用する Java コードは次のような感じです:

import org.xml.sax.ContentHandler;
import javax.xml.transform.Source;

public void parse(Source src, XMLStreamWriter writer){
    XMLEventParser parser = new XMLEventParser();
    XMLEventHandler handler = new StaxEventWriterHandler(writer);

    parser.pushparse(src, handler);
}

最初にも述べましたが、javax.xml.stream.XMLStreamWriter は StAXAPI ですが、使用しているのはプッシュ・パース (XMLEventParser#pushparse(..)) なのに注意。