4

XOMを使用して、膨大な数の検索結果をXMLとしてPrintWriterまたはOutputStreamに出力したいとします。結果のXMLは次のようになります。

<?xml version="1.0" encoding="UTF-8"?>
<resultset>
    <result>
       [child elements and data]
    </result>
    ...
    ...
    [1000s of result elements more]
</resultset>

結果のXMLドキュメントは大きくなる可能性があるため(おそらく数百メガバイト)、(ドキュメント全体をメモリに作成してから書き込むのではなく)ストリーミング形式で出力したいと思います。

一度に1つずつ出力する粒度は良いので、次々<result>に生成してストリームに書き込みたいと思います。<result>言い換えれば、私は単にこの擬似コードのようなことをしたいのです(自動フラッシュが有効になっているので、それについて心配しないでください):

open stream/writer
write declaration
write start tag for <resultset>
while more results:
    write next <result> element
write end tag for <resultset> 
close stream/writer

私は見てきましたSerializerが、必要なメソッド、、、writeStartTag(Element)は保護されており、公開されていませんwriteEndTag(Element)write(DocType)これらのメソッドを使用できるようにSerializerをサブクラス化する方法、またはXOMを完全にバイパスして開始タグと終了タグを文字列としてストリームに直接手動で書き込む以外に方法はありませんか?(後者はこの単純な例ではそれほど悪くはありませんが、一般的な場合はかなり醜くなります。)

私は何かが足りないのですか、それともXOMはこれのために作られていないのですか?

dom4jを使用すると、これを簡単に使用できます。これには、または、メソッド、などXMLWriterを受け取るコンストラクターがあります。パブリックメソッドが全体を受け取る唯一のメソッドであるXOMと比較してください。WriterOutputStreamwriteOpen(Element)writeClose(Element)writeDocType(DocumentType)SerializerwriteDocument

(これは、XOMが強力な候補である場合の最良のdom4j置換に関する私の質問に関連しています。)

4

2 に答える 2

7

同じ問題が発生しましたが、オプションとして言及したことを実行し、Serializerを次のようにサブクラス化するのは非常に簡単であることがわかりました。

public class StreamSerializer extends Serializer {

    public StreamSerializer(OutputStream out) {
        super(out);
    }

    @Override
    public void write(Element element) throws IOException {
        super.write(element);
    }

    @Override
    public void writeXMLDeclaration() throws IOException {
        super.writeXMLDeclaration();
    }

    @Override
    public void writeEndTag(Element element) throws IOException {
        super.writeEndTag(element);
    }

    @Override
    public void writeStartTag(Element element) throws IOException {
        super.writeStartTag(element);
    }

}

その後、setIdentなどのさまざまなXOM構成を引き続き利用できますが、次のように使用します。

Element rootElement = new Element("resultset");
StreamSerializer serializer = new StreamSerializer(out);
serializer.setIndent(4);
serializer.writeXMLDeclaration();
serializer.writeStartTag(rootElement);
while(hasNextElement()) {
    serializer.write(nextElement());
}
serializer.writeEndTag(rootElement);
serializer.flush();
于 2009-09-25T22:53:20.923 に答える
5

私の知る限り、XOM はストリーミングを直接サポートしていません。

XML ドキュメントをストリーミングしたいときに使用したのは、XOM の標準シリアライザー クラスに似たストリーミング XML シリアライザーを備えたNUXでした。NUX は XOM と互換性があります。NUX ソースをダウンロードし、いくつかの NUX クラス (StreamingSerializer インターフェイス、StreamingXMLSerializer - XOM ドキュメント、StreamingVerifier および NamespacesInScope で動作) を抽出し、それらをプロジェクトに入れました。残念ながら、これは XOM に直接含まれていません :-(

NUX は XOM の非常に優れたコンパニオンです: http://acs.lbl.gov/software/nux/、作業ミラーのダウンロード: nux-1.6.tar.gz

API へのリンク: http://acs.lbl.gov/software/nux/api/nux/xom/io/StreamingSerializer.html

サンプル コードは次のとおりです (メソッドは順番に呼び出されます: start()、 n* nextResult()finish()シリアライザーは NUX の StreamingXMLSerializer です)。

void start() {
    serializer.writeXMLDeclaration();

    Element root = new Element("response");
    root.addAttribute(new Attribute("found", Integer.toString(123)));
    root.addAttribute(new Attribute("count", Integer.toString(542)));

    serializer.writeStartTag(root);

    serializer.flush();
}

void nextResult(Result result) {
    Element element = result.createXMLRepresentation();
    serializer.write(element);
    serializer.flush();
}

void finish() {
    serializer.writeEndTag();
    serializer.flush();
}
于 2009-06-09T06:16:56.207 に答える