2週に渡ってStAXを使用したXMLドキュメントのパースについて紹介しました。今週は,XMLドキュメントを作成する方法を紹介しましょう。

StAXでXMLドキュメントを作成する

XMLドキュメントの作成でも,StAXは2種類の手法を持ちます。もちろん,パースと同様,カーソルAPIとイベントイテレータAPIです。

まずは,カーソルAPIでXMLドキュメントを作成しましてみます。

カーソルAPIを用いたXMLドキュメントの作成

作成するXMLドキュメントは次のような形式のものとしましょう。

<names>
  <name first="Bob" last="Dylan" />
  <name first="John" last="Lennon" />
  <name first="Chuck" last="Berry" />
</names>

names要素の中に,複数のname要素があります。name要素はfirst属性とlast属性を持ち,それぞれ文字列が入ります。

サンプルのソース CursorWriterSample.java

このサンプルはカーソルAPIを使用して,上記のXMLドキュメントを生成するプログラムです。

    public CursorWriterSample() {
        // ファクトリの生成
        XMLOutputFactory factory = XMLOutputFactory.newInstance();
 
        StringWriter stringWriter = new StringWriter();
        XMLStreamWriter writer = null;
 
        try {
            // ライタの生成
            writer = factory.createXMLStreamWriter(stringWriter);
 
            // XMLドキュメントの開始
            writer.writeStartDocument();
 
            // names要素
            writer.writeStartElement("names");
 
            // name要素
            writer.writeStartElement("name");
 
            // name要素の属性
            writer.writeAttribute("first", "Bob");
            writer.writeAttribute("last", "Dylan");
            
            // name要素を閉じる
            writer.writeEndElement();
            
            // names要素を閉じる
            writer.writeEndElement();
 
            // ドキュメントを閉じる
            writer.writeEndDocument();
            writer.flush();
 
            // ドキュメントの表示
            System.out.println(stringWriter);
        } catch (XMLStreamException ex) {
            System.err.println("出力に失敗しました");
        } finally {
            // クローズ
            if (writer != null) {
                try {
                    writer.close();
                } catch (XMLStreamException ex) {}
            }
            if (stringWriter != null) {
                try {
                    stringWriter.close();
                } catch (IOException ex) {}
            }
        }
    }

カーソルAPIを用いて,XMLドキュメントを作成するにはjavax.xml.stream.XMLStreamWriterインタフェースを使用します。XMLStreamWriterオブジェクトはファクトリを用いて,生成します。ファクトリはjavax.xml.stream.XMLOutputFactoryクラスです。

ファクトリを生成し,XMLStreamWriterオブジェクトを生成する部分を青字で示しました。

ファクトリはXMLOutputWriterクラスのnewInstanceメソッドをコールして生成し,createXMLStreamWriterメソッドでXMLStreamWriterオブジェクトを生成します。

この処理はパースの時のXMLStreamReaderオブジェクトを生成する処理とほぼ同じです。

createXMLStreamWriterメソッドの引数はストリーム,ライタ,またはXSLTで使用するリザルトが使用できます。ここでは,文字列に対する出力を行なうStringWriterクラスを使用しました。

XMLStreamWriterオブジェクトが取得できれば,後はXMLドキュメントを出力していくだけです。

XMLStreamWriterインタフェースにはパース時のイベントに応じた出力メソッドが用意されています。たとえば,要素の開始であればwriteStartDocumentメソッド,属性であればwriteAttributeメソッドを使用します。

上記のコードでは赤字で示した部分がXMLドキュメントの出力処理を表しています。特に難しい処理をしているわけではないので,容易に理解できるはずです。

この例では名前空間を指定していませんが,もちろん含めることも可能です。

このサンプルの実行結果を次に示します。

C:\stax>java StreamWriterSample
<?xml version="1.0" ?><names><name first="Bob" last="Dylan"></name></names>

内容は意図した通りですが,すべて1行に記述されてしまいました。

読みやすいように整形して出力するのであれば,適宜writeCharactersメソッドを使用して改行や空白を加えていきます。以下に,改行,空白を加えたコードを示します。

    public CursorWriterSample() {
        // ファクトリの生成
        XMLOutputFactory factory = XMLOutputFactory.newInstance();
 
        StringWriter stringWriter = new StringWriter();
        XMLStreamWriter writer = null;
 
        try {
            // ライタの生成
            writer = factory.createXMLStreamWriter(stringWriter);
 
            // XMLドキュメントの開始
            writer.writeStartDocument();
            writer.writeCharacters("\n");
 
            // names要素
            writer.writeStartElement("names");
            writer.writeCharacters("\n  ");
 
            // name要素
            writer.writeStartElement("name");

            // name要素の属性
            writer.writeAttribute("first", "Bob");
            writer.writeAttribute("last", "Dylan");
            
            // name要素を閉じる
            writer.writeEndElement();
            writer.writeCharacters("\n");
            
            // names要素を閉じる
            writer.writeEndElement();
  
            // ドキュメントを閉じる
            writer.writeEndDocument();
            writer.flush();
            
            // ドキュメントの表示
            System.out.println(stringWriter);
        } catch (XMLStreamException ex) {
            System.err.println("出力に失敗しました");
        } finally {
            // クローズ
            if (writer != null) {
                try {
                    writer.close();
                } catch (XMLStreamException ex) {}
            }
            if (stringWriter != null) {
                try {
                    stringWriter.close();
                } catch (IOException ex) {}
            }
        }
    }

赤字の部分が改行もしくは空白を出力している部分です。これで実行すると次のようになります。

C:\stax>java StreamWriterSample
<?xml version="1.0" ?>
<names>
  <name first="Bob" last="Dylan"></name>
</names>

このようにシーケンシャルに出力をしていくことで,XMLドキュメントを作成していくことができます。