17

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 ネットワーク ライブラリでうまく機能するものが欲しいからです。

4

7 に答える 7

7

驚くべきことに、ノンブロッキング (「非同期」) 解析を実装する Java XML パーサー、 Aaltoについて誰も言及していません。その理由の一部は、ドキュメントの不足 (およびその活動レベルの低さ) である可能性があります。Aalto は基本的な Stax API を実装していますが、プッシュ入力を可能にするマイナーな拡張機能も実装しています (この部分は最終決定されていません。機能は存在しますが、API は最終決定されていません)。詳細については、関連するディスカッション グループを参照してください。

于 2010-08-31T05:44:45.183 に答える
4

編集:わかりました。XML をチャンクで受け取り、それを適切な XML パーサーに送りたいとします。では、一方がキューで、もう一方が InputStream であるオブジェクトが必要ですか?

受信したバイト配列を ByteArrayOutputStream に集約し、それを ByteArrayInputStream に変換して、SAXParser に渡すことができます。

または、PipedInputStream/PipedOutputStream ペアをチェックアウトすることもできます。この場合、SAX パーサーは現在のスレッドを使用してイベントを発行し、receive() をブロックするため、別のスレッドで解析を行う必要があります。

編集:コメントに基づいて、集約ルートを取ることをお勧めします。チャンクを ByteArrayOutputStream に収集します。XML のすべてのチャンクを受信したかどうかを確認するには、現在のチャンクまたは ByteArrayOutputStream の内容に XML ルート ノードの終了タグが含まれているかどうかを確認します。次に、データを SAXParser に渡すだけで、現在のスレッドで問題なく実行できるようになります。不必要な配列の再作成を避けるために、独自の非同期の単純なバイト配列ラッパーを実装するか、そのような実装を探すことができます。

于 2009-06-21T20:09:12.197 に答える
3

これは (2009 年 4 月) Xerces J-Users メーリング リストからの投稿で、元の投稿者がまったく同じ問題を抱えています。"Jeff" からの潜在的に非常に良い応答が 1 つ示されていますが、元の投稿者の応答へのフォローアップはありません。

http://www.nabble.com/parsing-an-xml-document-chunk-by-chunk-td22945319.html

リストに載ったり、少なくとも検索に役立つほど新しい可能性があります。

編集

Woodstox と呼ばれるライブラリに言及し、ストリームと NIO ベースのパーサーの状態、およびストリームをエミュレートするためのいくつかの可能なアプローチについて説明している、別の有用なリンクを見つけました。

http://markmail.org/message/ogqqcj7dt3lwkbov

于 2009-06-25T20:37:26.317 に答える
1

この質問は関連するGoogle検索で高いままであるため、別の回答を追加します-aalto-xml 0.9.7(2011年3月)には非同期XMLペーシングがあります。これにより、ドキュメントの任意のサイズのチャンクを渡して解析を続行できEVENT_INCOMPLETE、入力バッファーが使い果たされてドキュメントが不完全なままであることを示す新しいStaXイベントタイプが可能になります。

これはTatuSalorant(作者)の例です:

     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);
于 2012-06-21T09:47:54.690 に答える
1

openfire のXMLLeightweightParser と、NIO が原因で単一のチャンクから XML メッセージを生成する方法を確認してください。プロジェクト全体は、NIO および XMPP に関する質問に対する回答の優れた情報源です。

于 2009-07-31T20:04:20.263 に答える
0

申し訳ありませんが、この問題を解決できませんでした。必要なパーサーが見つかりませんでした。でも自分で書こうと思っています。非常に単純なものです。忠実度の調査と同じですが、私の問題とうまくいけばあなたの問題を解決するのに十分です。残念ながら、私はとても元気で、次の2週間は外出する予定ですが、おそらく7月に作業を開始します。何か動作があり次第お知らせします。

mt

于 2009-06-25T23:34:20.063 に答える