[Java] 非常に大きなXML文書の解析(ともう少し)


Answers

これはStAX( JSR 173 )の仕事のようです。 StAXはプル・パーサです。つまり、SAXのようなイベント・ベースのパーサのように動作しますが、いつ読み込みを停止するか、どの要素をプルするかをより詳細に制御できます。

このソリューションの使い勝手は、あなたの拡張クラスが実際にやっていることに大きく依存します。

要点は、文書が非常に大きい場合は、ツリーベースではなくイベントベースのパーサを使用することが多いため、多くのメモリを使用しないことです。

StAXの実装はSUN( SJSXP )、 Codehausまたは他のいくつかのプロバイダから見つけることができます。

Question

(以下はすべてJavaで書かれています)

私は、潜在的に非常に大きい入力XML文書をとるアプリケーションを構築する必要があります。 ドキュメントは暗号化されています(XMLsecではなく、クライアントの既存の暗号化アルゴリズムを使用)が3つの段階で処理されます。

最初に、ストリームは前述のアルゴリズムに従って復号化される。

次に、拡張クラス(私が提供しているAPIの第三者によって書かれたもの)がファイルの一部を読み込みます。 読み込まれる量は予測できません。特に、ファイルのヘッダーにあることは保証されていませんが、XMLの任意の時点で発生する可能性があります。

最後に、別の拡張クラス(同じ取引)は、入力XMLを1つのサブセット文書に分割します。 これらは、第2の操作によって処理される文書の部分と一部重複する可能性があります。つまり、このオブジェクトを処理するために使用しているメカニズムを巻き戻す必要があると考えています。

ここに私の質問です:

一度にすべてのデータをメモリに読み込まずにこれを行う方法はありますか? 明らかに私は入力ストリームフィルタとして復号化を実装することができますが、私が記述している方法でXMLを解析することが可能かどうかはわかりません。 次のステップの情報を収集するために必要なだけの文書を歩いて行き、文書を巻き戻してもう一度渡してジョブに分割し、理想的には文書の後にもう使用されていない部分のすべてを解放する彼らは渡されました。




XOMライブラリを見てください。 探している例は、ソース配布のsamplesディレクトリにあるStreamingExampleExtractor.javaです。 これは、特定のノードを構築し、処理して破棄する大規模XML文書のストリーミング解析を実行するための手法を示しています。 これはサックスの手法に非常に似ていますが、ストリーミング解析を非常に簡単に行うことができるように、より多くの解析機能が組み込まれています。

あなたがより高いレベルでNUXを見て作業したい場合。 これは、xpathを評価するために必要なメモリへのデータ量だけを読み込む、高水準のストリーミングxpath APIを提供します。




私はInputStreamカスタム実装を書いて、ファイル内のバイトを復号化し、 SAXを使用してストリームから取り出されたXMLを解析します。

SAXParserFactory.newInstance().newSAXParser().parse(
  new DecryptingInputStream(), 
  new MyHandler()
);