web-dev-qa-db-ja.com

SAXとJavaを使用してXMLを生成する

SAXフレームワーク(または同様のもの)とJavaを使用してXMLを作成するための優れたチュートリアル(または良い例があります)を知っている人はいますか?検索を行っても、有用な結果はほとんど得られていません。 Androidアプリからエクスポートしようとしています。できるだけ多くのメモリオーバーヘッドを回避しようとしています。

18
Lunchbox

SAXフレームワーク(SAXパーサーではなくSAXフレームワーク)を介してPOJOから直接generatingXMLを作成するための非常に便利な手法があります。この手法は、XMLドキュメントの生成に使用できます。

任意のデータ構造からのXMLの生成
http://download.Oracle.com/javaee/1.4/tutorial/doc/JAXPXSLT5.html

基本的に、POJOにメソッドを追加するか、POJOのユーティリティクラスを記述して、それらをSAXイベントエミッターに変換します(XMLドキュメントの解析時に通常SAXパーサーのようなイベントを発行します)。これで、「SAXイベントジェネレータ」はSAXパーサーの出力側のようになり、SAXパーサーが取る任意のコンテンツハンドラー(XMLをきれいに出力するハンドラーなど)を与えることができます。ただし、DOMパーサーにフィードしてDOMツリーを生成したり、XSLTエンジンにフィードしてHTMLを生成したり、最初にPOJOから中間XMLドキュメントを生成しなくても、真のXSL変換を実行したりできます。

たとえば、Personクラスには、次の行を含むemitXML()メソッドがある場合があります。

handler.startElement(nsu, PERSON_TAG, PERSON_TAG, NO_ATTRIBUTES);

handler.startElement(nsu, FIRSTNAME_TAG, FIRSTNAME_TAG, atts);
handler.characters(this.firstName.toCharArray(), 
        0,
        this.firstName.length());
handler.endElement(nsu, FIRSTNAME_TAG, FIRSTNAME_TAG);

... emit more instance variables

... emit child object like: homeAddress.emitXML(handler, ...);

handler.endElement(nsu, PERSON_TAG, PERSON_TAG);

更新:

その他の参考文献:


コメントに対するいくつかの応答:

これは事実ですが、上記のXMLStreamWriterインターフェースははるかにユーザーフレンドリーです。 –マイケル・ケイ3時間前

はい、しかし私ははっきりしていなかったと思います。私は簡単に階層をトラバースし、XMLStreamWriterを使用してXMLドキュメントをストリームに直接出力できます。 ただし、記事では、XMLドキュメントを直接出力するのではなく、階層をトラバースしてSAXイベントを生成する強力な手法を示しています。これで、さまざまなことを実行したり、XMLのさまざまなバージョンを生成したりするさまざまなコンテンツハンドラーをプラグインできます。 XSLTエンジンなど、SAXパーサーを受け入れる任意のツールにオブジェクト階層をフィードすることもできます。これは本当に、SAXフレームワークによって確立されたビジターパターンを利用するだけです。XMLの出力から階層のトラバースを分離します。 XMLストリームを書き込むことを目的とする場合は、XMLを出力する部分であるコンテンツハンドラーでXMLStreamWriterを使用する必要があります。

たとえば、このプログラムでは、分散コンポーネント間のネットワークソケットを介してXMLメッセージを送信し、XSLTを使用してHTMLページを生成しました。以前は、階層をたどってXMLドキュメント(文字列)を生成し、そのXMLドキュメントをネットワークソケットに書き込むか、そのドキュメントをXSLTエンジン(基本的には再度解析するだけ)にフィードしていました。この手法を使用した後は、中間のXML文字列を必要とせずに、(このSAXアダプターを使用して)オブジェクト階層をXSLTエンジンに直接供給することができます。また、1つのコンテンツハンドラーを使用してネットワークストリームのコンパクトなXML表現を生成し、別のコンテンツハンドラーを使用して、きれいに印刷されたXMLドキュメントを生成してログファイルに書き込むことができると便利でした。

さらに、SAXパーサーAPIを使用してXMLを作成することは、APIの誤用です。 – 49分前のPuce

たぶん、それはあなたのニーズ次第だと思います。 OPの要件が特定のXMLドキュメントを書き出すことだけである場合、これは間違いなく過剰です。ただし、OPが彼のプロジェクトで言及していない他の方法でOPがXMLを使用する場合は、言及する価値があると思いました。代替案を提案しても害はありません。

それをmisuseと呼ぶのは少し強いかもしれませんが、あなたがあなたの意見を受ける権利があることに同意します。 Oracleチュートリアルに記載されているため、Sun/Oracleエンジニアによる悪用とは見なされません。私たちのプロジェクトでは、大きな不利な点なしに要件を満たすことができたので大成功でした。そのため、このアプローチをツールボックスに保存し、将来的に役立つようにします。

16
Bert F

SAX解析は、文書を読み取るためのものであり、文書を書き込むためのものではありません。

XMLStreamWriterを使用してXMLを書き込むことができます。

OutputStream outputStream = new FileOutputStream(new File("doc.xml"));

XMLStreamWriter out = XMLOutputFactory.newInstance().createXMLStreamWriter(
                new OutputStreamWriter(outputStream, "utf-8"));

out.writeStartDocument();
out.writeStartElement("doc");

out.writeStartElement("title");
out.writeCharacters("Document Title");
out.writeEndElement();

out.writeEndElement();
out.writeEndDocument();

out.close();
33
morja

以下の回答「SAXパーサーとJavaを使用してXMLを作成するための優れたチュートリアル」質問の一部

あなたがこれを経験したかどうかはわかりません。しかし、私は本当に好きです JavaのReally Big Index of Everything

これを通過します: http://download.Oracle.com/javase/tutorial/jaxp/index.html

そして最終的には、これ: http://download.Oracle.com/javase/tutorial/jaxp/sax/index.html

5
Nishant

私の個人的なブログ投稿を参照してください: JavaでのXML生成 -具体的には SAXメソッド 。これは、これに関する他のいくつかの記事を参照し、具体的な例を提供し、JavaからXMLを生成するための他の一般的なAPIとSAXを比較します。

(これは古い質問であることに気付きましたが、同じ質問を持つ可能性のある他の人にはこれを追加する必要があると感じました。)

4
ziesemer

また、XMLの書き込み/読み取りについてはJAXBを検討してください。

3
Puce

これを使用してtraxにブリッジすることもできます。

public abstract class PipedSAXSource extends SAXSource {
  protected PipedSAXSource() {
    setXMLReader(new CallWriteDuringSax());
  }

  protected abstract void writeTo(ContentHandler sink)
      throws IOException, SAXException;

  private class CallWriteDuringSax extends XMLFilterImpl {
    @Override
    public void parse(InputSource ignored) throws IOException, SAXException {
      writeTo(getContentHandler());
    }

    @Override
    public void setFeature(String name, boolean value) {}
  }
}

そのように使用してください:

  public static void main(String[] args) throws Exception {
    Source in = new PipedSAXSource() {
      @Override
      protected void writeTo(ContentHandler sink) throws SAXException {
        sink.startDocument();

        sink.startElement("", "root", "root", new AttributesImpl());
        sink.endElement("", "root", "root");

        sink.endDocument();
      }
    };

    Transformer identity = TransformerFactory.newInstance().newTransformer();
    identity.transform(in, new StreamResult(System.out));
  }
1
slow