Java用のプッシュベース/非ブロッキングXMLパーサーはありますか?
-
06-07-2019 - |
質問
InputStreamまたはInputSourceから解析する代わりに、テキストブロックをパーサーにプッシュできるXMLパーサーを探しています。例えば。次のようなものが欲しいです:
public class DataReceiver {
private SAXParser parser = //...
private DefaultHandler handler = //...
/**
* Called each time some data is received.
*/
public void onDataReceived(byte[] data) {
parser.push(data, handler);
}
}
理由は、ブロッキングInputStreamをサポートするために必要な接続モデルごとにスレッドに戻す必要があるのではなく、NIOネットワークライブラリでうまく動作するものが欲しいからです。
解決
これは、Xerces J-Usersメーリングリストの(2009年4月)投稿です。元の投稿者はまったく同じ問題を抱えています。 「Jeff」による非常に良い応答の可能性与えられますが、元のポスターの応答へのフォローアップはありません:
http://www.nabble .com / parsing-an-xml-document-chunk-by-chunk-td22945319.html
リストに載るほど、または少なくとも検索に役立つほど潜在的に新しいものです。
編集
Woodstoxと呼ばれるライブラリに言及し、Stream vs. NIOベースのパーサーの状態とストリームをエミュレートするためのいくつかの可能なアプローチを説明する別の有用なリンクを見つけました:
他のヒント
驚いたことに、ノンブロッキング(" async")解析を実装するJava XMLパーサーについて言及した人はいませんでした:アアルト。理由の一部は、ドキュメントの不足(およびその低レベルのアクティビティ)である可能性があります。 Aaltoは、基本的なStax APIを実装しますが、入力をプッシュできるようにするためのマイナーな拡張機能も実装します(この部分は最終化されていません。機能は存在しますが、APIは最終化されません)。 詳細については、関連するディスカッショングループをご覧ください。
>編集:わかりました。 XMLをチャンク単位で受け取り、適切なXMLパーサーにフィードします。オブジェクトが必要です。これは、一端にキューがあり、他端にInputStreamがありますか?
受信したバイト配列をByteArrayOutputStreamに集約し、ByteArrayInputStreamに変換して、SAXParserに供給することができます。
または、PipedInputStream / PipedOutputStreamペアをチェックアウトすることもできます。この場合、SAXパーサーは現在のスレッドを使用してイベントを発行し、receive()をブロックするため、別のスレッドで解析を行う必要があります。
編集:集約ルートを取ることをお勧めするコメントに基づきます。チャンクを収集してByteArrayOutputStreamにします。 XMLのすべてのチャンクを受信したかどうかを確認するには、現在のチャンクまたはByteArrayOutputStreamのコンテンツにXMLルートノードの終了タグが含まれているかどうかを確認します。次に、データをSAXParserに渡すだけで、現在のスレッドで問題なく実行できます。不要な配列の再作成を回避するには、独自の非同期の単純なバイト配列ラッパーを実装するか、そのような実装を探すことができます。
openfireの XMLLeightweightParserと、単一のチャンクからXMLメッセージを生成する方法を確認します。 NIOの。プロジェクト全体は、NIOおよびXMPPの質問に関する回答の素晴らしいソースです。
この質問が関連するGoogle検索に対して高いままであるため、別の回答を追加します- aalto-xml 0.9。 7(2011年3月)には非同期XMLのパッシングがあります。これにより、ドキュメントの任意のサイズのチャンクを渡して解析を続けることができ、新しいStaXイベントタイプ EVENT_INCOMPLETE
を使用して、入力バッファが使い果たされ、ドキュメントが不完全なままであることを示します。
これは Tatu Salorantの(著者)の例です。
byte[] msg = "<html>Very <b>simple</b> input document!</html>".getBytes();
AsyncXMLStreamReader asyncReader = new InputFactoryImpl().createAsyncXMLStreamReader();
final AsyncInputFeeder feeder = asyncReader.getInputFeeder();
int inputPtr = 0; // as we feed byte at a time
int type = 0;
do {
// May need to feed multiple "segments"
while ((type = asyncReader.next()) == AsyncXMLStreamReader.EVENT_INCOMPLETE) {
feeder.feedInput(msg, inputPtr++, 1);
if (inputPtr >= msg.length) { // to indicate end-of-content (important for error handling)
feeder.endOfInput();
}
}
// and once we have full event, we just dump out event type (for now)
System.out.println("Got event of type: "+type);
// could also just copy event as is, using Stax, or do any other normal non-blocking handling:
// xmlStreamWriter.copyEventFromReader(asyncReader, false);
} while (type != AsyncXMLStreamReader.END_DOCUMENT);
NioSaxはByteBuffersで動作します
http:/ /blog.retep.org/2010/06/25/niosax-sax-style-xml-parser-for-java-nio/
最新バージョン(2010年の10.6)のソースコードは、 Sonatype Mavenリポジトリ:
https://oss.sonatype.org/content/repositories / releases / uk / org / retep /
申し訳ありませんが、この問題を解決できませんでした。 必要なパーサーが見つかりませんでした。 しかし、私は自分で書いてみたいと思っています。 非常に簡単なもの:単純なフィジビリティ研究ですが、私の問題を解決するのに十分であり、うまくいけばあなたのものです。 Unortunatelly私はとても元気で、次の2週間は外出します。 しかし、おそらく7月に作業を開始します。 何か問題がありましたらすぐにお知らせします。
mt