今回と次回で、javax.xml.transform パッケージのクラスへのブリッジを考えます。 基本的な考え方は XMLEvent がベースです。 定義するクラスは XMLEvent を読み込む XMLEventSource と XMLEvent を書き出す XMLEventResult です。
今回は javax.xml.transform.Source インターフェース。
XMLEventSource
まず、「こんな風に使えるようにしよう」というサンプルコード。 XMLEventSource クラスは Source のサブタイプです。
public void someMethod(XMLEventIterator iterator){ Source src = new XMLEventSource(iterator); ... }
XMLEventIterator オブジェクトから Source オブジェクトを生成しています。 前回までに作成したクラス群では XMLEventIterator オブジェクトの生成に Source オブジェクトを使用していたので、正直これはあまり使いようがないかも。 XMLEventParser 以外で XMLEventIterator を生成するクラスなどを作成すれば使えますよって程度です。
まぁ、ともあれこの実装を考えていきましょう。
XMLEventSource の実装
新に Source オブジェクトを一から作成するのは大変なので、既にあるプル・パース型の Source クラス、javax.xml.transform.stax.StAXSource を利用しましょう。 StaxEventReader は javax.xml.stream.XMLEventReader を実装したクラスで、後ほど詳しくみていきます。
package xmlparsing.transform; import javax.xml.stream.XMLStreamException; import javax.xml.transform.stax.StAXSource; import xmlparsing.XMLEventIterator; import xmlparsing.stax.StaxEventReader; public class XMLEventSource extends StAXSource{ public XMLEventSource(XMLEventIterator iterator)throws XMLStreamException{ super(new StaxEventReader(iterator)); } }
StaxEventReader
これは javax.xml.stream.XMLEventReader を実装し、その処理(XML イベントの列挙)を XMLEventIterator へ委譲するクラスです。 同じ XMLEvent という名前の型でも別の型なので、オブジェクトの変換(生成)が必要です。 StaxEventReader の実装は以下のようになります(いくつかメソッドの実装を略しています):
package xmlparsing.stax; import javax.xml.stream.XMLEventFactory; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLStreamException; import javax.xml.stream.events.XMLEvent; import xmlparsing.XMLEventIterator; public class StaxEventReader implements XMLEventReader{ private final XMLEventIterator iterator; private XMLEvent next; public StaxEventReader(XMLEventIterator iterator){ this.iterator = iterator; if(iterator.hasNext()) this.next = toStaxEvent(iterator.next()); } public boolean hasNext() { return this.next != null; } public Object next() { try{ return nextEvent(); }catch(XMLStreamException ex){ throw new RuntimeException(ex); } } public XMLEvent nextEvent() throws XMLStreamException { XMLEvent nextEvent = this.next; if(this.iterator.hasNext()) this.next = toStaxEvent(this.iterator.next()); return nextEvent; } /** * xmlparsing.events.XMLEvent オブジェクトから * (javax.xml.stream.events.)XMLEvent オブジェクトを生成するメソッド。 */ private static XMLEvent toStaxEvent(xmlparsing.events.XMLEvent event){...} public void close() throws XMLStreamException { this.iterator.close(); } public Object getProperty(String name) throws IllegalArgumentException {} public XMLEvent nextTag() throws XMLStreamException {...} public String getElementText() throws XMLStreamException {...} public XMLEvent peek() throws XMLStreamException {...} public void remove() { throw new UnsupportedOperationException(); } }
XMLEventReader インターフェースには、実装が少々難しい(メンドクサイ)メソッドもありますが、XMLEventReader も XMLEventIterator もプル・パース API なので、論理的に難しいところはあまりないでしょう。
XMLEventReader に定義されている便利そうなメソッドは XMLEventIterator にも定義しておくのも良いかもしれません。
次回は javax.xml.transform.Result を実装したクラスを考えます。