StAXとXSLTを連携させる
Java SE 6で導入されたStAXを扱うため,XSLTも機能拡張されています。具体的にはXSLTトランスフォーマへの入力となるソース,そして出力となるリザルトに,StAX用のクラスが提供されたのです。
そこで,今週はXSLTとStAXを連携させてみましょう。ただし,本記事はStAXの紹介記事であるため,XSLTに関する説明は必要最低限に留めておきます。
まずは単純にStAX用のソースもしくはリザルトを使用するところからはじめてみます。
StAX用のソースはjavax.xml.transform.stax.StAXSrouceクラス,そしてリザルトはjavax.xml.transform.stax.StAXResultクラスとなります。
先週までの紹介で,StAXにはカーソルAPIとイベントイテレータAPIがあることはお分かりだと思います。ソース,そしてリザルトもこの2種類のAPIを扱うことができます。
StAXSourceクラスのコンストラクタには次の2種類があり,引数の型の違いによりカーソルAPIとイベントイテレータAPIを切り替えることができます。
- StAXSource(XMLStreamReader xmlStreamReader)
- StAXSrouce(XMLEventReader xmlEventReader)
同様にStAXResultクラスのコンストラクタもオーバロードされています。
- StAXResult(XMLStreamWriter xmlStreamWriter)
- StAXResult(XMLEventWriter xmlEventWriter)
ここではカーソルAPIを使うことにしましょう。
サンプルのソース | StAXTransformSample1.java |
---|
このサンプルでは,XSLTは何も変換せずに(恒等変換),ソースからリザルトにコピーを行ないます。
public StAXTransformSample1(String xmlfile) { XMLInputFactory inFactory = XMLInputFactory.newInstance(); XMLOutputFactory outFactory = XMLOutputFactory.newInstance(); XMLStreamReader reader = null; BufferedInputStream stream = null; XMLStreamWriter writer = null; try { // ソースの生成 stream = new BufferedInputStream( new FileInputStream(xmlfile)); reader = inFactory.createXMLStreamReader(stream); Source source = new StAXSource(reader); // リザルトの生成 StringWriter stringWriter = new StringWriter(); writer = outFactory.createXMLStreamWriter(stringWriter); Result result = new StAXResult(writer); // XSLTトランスフォーマの生成 TransformerFactory transFactory = TransformerFactory.newInstance(); Transformer transformer = transFactory.newTransformer(); // 変換 transformer.transform(source, result); System.out.println(stringWriter); } catch (TransformerConfigurationException ex) { ex.printStackTrace(); } catch (TransformerException ex) { ex.printStackTrace(); } catch (FileNotFoundException ex) { System.err.println(xmlfile + " が見つかりません"); } catch (XMLStreamException ex) { System.err.println(xmlfile + " の読み込みに失敗しました"); } finally { // パーサ,ストリームのクローズ if (reader != null) { try { reader.close(); } catch (XMLStreamException ex) {} } if (writer != null) { try { writer.close(); } catch (XMLStreamException ex) {} } if (stream != null) { try { stream.close(); } catch (IOException ex) {} } } }
赤字で示した部分がソースおよびリザルトを生成している部分です。
ソースを生成する前にXMLStreamReaderオブジェクトを生成します。そして,そのXMLStreamReaderオブジェクトをStAXSrouceクラスのコンストラクタの引数に指定します。同様にリザルトもXMLStreamWritterオブジェクトを生成し,StAXResultクラスのコンストラクタに指定します。
青字で示したのがXSLTの処理部分です。XSLTトランスフォーマもファクトリを介して生成します。実際に変換を行なうのが,Transformerクラスのtransformメソッドです。transformメソッドの第1引数の型がSourceインタフェース,第2引数の型がResultインタフェースです。
このサンプルを見ると,StreamSourceクラスやDOMResultクラスを扱うのとほとんど変りません。XSLTの使い方が分かっていれば,StAXに対応させるのは簡単だということが分かります。
では,実行してみましょう。変換を行なうのは,今月何度も登場しているnames.xmlです。
<?xml version="1.0" encoding="utf-8"?> <names> <name> <first>Bob</first> <last>Dylan<last> </name> <name> <first>Paul</first> <last>Simon</last> </name> <name> <first>Pete</first> <last>Seeger</last> </name> </names>
実行結果を以下に示します。
C:\stax>java StAXTransformSample1 names.xml <?xml version="1.0"?><names> <name> <first>Bob</first> <last>Dylan</last> </name> <name> <first>Paul</first> <last>Simon</last> </name> <name> <first>Pete</first> <last>Seeger</last> </name> </names>
names要素の開始位置は異なりますが,内容はnames.xmlと同一であることが分かります。