ドキュメントのノードを探すために DOM ドキュメント全体を再構築しない XPath エバリュエーターを探しています。メモリ管理に適しており、ノードを検索する可能性を提供します。
応援ありがとうございました!
不可能だと言うすべての人のために: 私は最近、質問をした後、「saxpath」( http://www.saxpath.org/ ) という名前のプロジェクトを見つけましたが、実装プロジェクトが見つかりません。
ドキュメントのノードを探すために DOM ドキュメント全体を再構築しない XPath エバリュエーターを探しています。メモリ管理に適しており、ノードを検索する可能性を提供します。
応援ありがとうございました!
不可能だと言うすべての人のために: 私は最近、質問をした後、「saxpath」( http://www.saxpath.org/ ) という名前のプロジェクトを見つけましたが、実装プロジェクトが見つかりません。
私の現在のリスト(Web検索結果と他の回答から編集)は次のとおりです。
次のステップは、XMLDog の例を使用して、これらすべてのアプローチのパフォーマンスを比較することです。次に、サポートされている XPath 式にテスト ケースを拡張する必要があります。
XPath を使用して簡単に照会できる部分的な DOM ツリーを抽出する SAX パーサーを使用して、1GB 以上の複雑な XML ファイルを定期的に解析します。http://softwareengineeringcorner.blogspot.com/2012/01/conveniently-processing-large-xml-files.html - ソースはgithubで入手できます- MIT ライセンス。
XPathはSAXで動作し、ほとんどのXSLTプロセッサー(特にSaxonおよびApache Xalan)は、dom全体を構築せずにSAXストリーム上のXSLT内でXPath式を実行することをサポートします。
彼らは次のように、これを非常に大まかに行うことができます:
それらがどのようにバッファリングするかも非常に興味深いです。なぜなら、あちこちでDOMフラグメントを作成するだけの人もいれば、非常に最適化されたテーブルを使用してすばやくルックアップし、メモリ消費を減らす人もいます。
彼らがどれだけ最適化できるかは、彼らが見つけたXPathクエリの種類に大きく依存します。すでに投稿されているSaxonのドキュメントで明確に説明されているように、ドキュメントを「上」に移動してから「水平に」(兄弟ごとに)トラバースするクエリでは、ドキュメント全体がそこにある必要がありますが、ほとんどの場合、いくつかのノードを保持する必要があります。いつでもRAM。
これは、Cocoonを使用して毎日Webアプリを作成しているときに、XSLT内で「//何か」式を使用するたびにXSLTメモリフットプリントの問題が発生し、XPath式を作り直さなければならないことが多かったためです。より良いSAX最適化を可能にするため。
SAX は前方のみですが、XPath クエリは任意の方向にドキュメントをナビゲートできます ( parent::
、ancestor::
、preceding::
およびpreceding-sibling::
軸を考慮してください)。これが一般的にどのように可能になるかわかりません。最良の概算は、ある種の遅延ロード DOM ですが、クエリによっては、これがメリットをもたらす場合ともたらさない場合があります//*[. != preceding::*]
。
申し訳ありませんが、ここで少し遅い回答です-これはXPathのサブセットで可能であるようです-一般に、XPathは「現在の」ポイントから前方と後方の両方に一致する可能性があるため、非常に困難です。ステート マシンを使用してある程度解決する 2 つのプロジェクトを認識しています: http://spex.sourceforge.net & http://www.cs.umd.edu/projects/xsq。私はそれらを詳しく見ていませんが、同様のアプローチを使用しているようです。
AXS と呼ばれる私の新しいプロジェクトのプラグインを投げます。https://code.google.com/p/annotation-xpath-sax/にあり、(前方軸のみの) XPath ステートメントでメソッドに注釈を付け、SAX パーサーがノードにあるときに呼び出されるという考え方です。それはそれに一致します。だから書類で
<doc>
<nodes>
<node name="a">text of node 1</node>
<node name="b">text of node 2</node>
<node otherattr="I have attributes!">text of node 3</node>
</nodes>
</doc>
次のようなことができます
@XPath("/nodes/node")
void onNode(String nodeText)
{
// will be called with "text of node [123]"
}
また
@XPathStart("//node[@name='']")
void onNode3(Attrs node3Attrs) { ... }
また
@XPathEnd("/nodes/node[2]")
void iDontCareAboutNode3() throws SAXExpression
{
throw new StopParsingExpression();
}
もちろん、このライブラリは非常に新しいため、まだリリースすらしていませんが、MIT ライセンスなので、気軽に試してみて、ニーズに合っているかどうかを確認してください。(古い Android デバイスで実行できるように十分に低いメモリ要件で HTML スクリーンスクレイピングを行うために作成しました...) バグを見つけた場合は、googlecode サイトにファイルしてお知らせください。
SAX/StAX ベースの XPath 実装がありますが、主に SAX/StAX の前方のみの性質により、XPath 式/軸の小さなサブセットしかサポートしていません。私が知っている最良の代替手段は拡張VTD-XMLで、完全な xpath をサポートしていますmem-map を介した部分的なドキュメントの読み込み.. 最大ドキュメント サイズは 256 GB ですが、最大限に活用するには 64 ビット JVM が必要です。
Saxon-SA XSLT プロセッサのストリーミング モードを見てください。
http://www.saxonica.com/documentation/sourcedocs/serial.html
「パス式をストリーミングできるかどうかを決定するルールは次のとおりです。
doc() またはドキュメントの呼び出しによって導入されるパス式は、次のように定義された XPath のサブセットに準拠する必要があります。
XML スキーマの ID 制約に現れるパス式の規則に準拠している場合、任意の XPath 式を使用できます。これらの規則では、述語は許可されません。最初のステップ (最初のみ) は "//" で導入できます。最後のステップでは、オプションで属性軸を使用できます。他のすべてのステップは、子軸を使用する単純な軸ステップでなければなりません。
式では、要素のみ、属性のみ、または要素と属性の混合のいずれかを選択する必要があります。
単純なフィルター (1 つ以上) もサポートされています。各フィルターは、最後のステップまたは式全体に適用でき、コンテキスト ノード (自己、子、属性、子孫、子孫または自己、または名前空間軸) からの下方選択のみを使用する必要があります。位置指定であってはなりません (つまり、position() または last() を参照してはならず、数値であってはなりません。実際、Saxon がコンパイル時に数値ではないことを判断できるようなものでなければなりません)。フィルタは、ユニオンまたはユニオンのブランチには適用できません。これらの条件に違反すると、ストリーミングの最適化なしで式が評価されます。
これらのルールは、他の最適化の書き換えが式に適用された後に適用されます。たとえば、一部の FLWOR 式は、これらの規則を満たすパス式に書き換えられる場合があります。
最適化は、saxon:stream() 拡張関数、XSLT xsl:copy-of 命令の saxon:read-once 属性、または XQuery プラグマ saxon:stream を使用して、明示的に要求された場合にのみ有効になります。スタイルシートまたはクエリが Saxon-SA を使用して処理されている場合にのみ使用できます。"
注: この機能は、商用バージョンで利用できる可能性が最も高いです。私はこれまで Saxon を広範囲に使用してきましたが、これはすばらしい作業です。
できることは、XSL トランスフォーマーを SAX 入力ソースにフックすることです。処理は逐次的に行われ、XSL プリプロセッサは入力をキャッチして、指定された結果に変換しようとします。これを使用して、パスの値をストリームから引き出すことができます。これは、1 回のパスで多数の異なる XPATH 結果を生成したい場合に特に便利です。
結果として (通常は) XML ドキュメントが得られますが、予想される出力を、たとえば a からStreamResult
それほど手間をかけずに引き出すことができます。
うーん、本当にあなたを理解しているかどうかはわかりません。私の知る限り、SAXモデルはイベント指向です。つまり、解析中に特定のノードが検出された場合に何かを実行します。ええ、それはメモリにとっては良いのですが、XPathをどのように取り入れたいのかわかりません。SAXはモデルを作成しないので、これは不可能だと思います。
標準の javax xpath API は、技術的にはすでにストリームで動作します。javax.xml.xpath.XPathExpression
に対して評価することがInputSource
でき、それを で構築することができますReader
。裏でDOMを構築しているとは思いません。
xpath は SAX では機能しないと思いますが、Java 用の拡張ストリーミング XML API である StAX を検討してみてください。