私は、ドキュメントのノードを探すためにDOMドキュメント全体を再構築しないXPathエバリュエーターを探しています。実際には、オブジェクトはSAXモデルで大量のXMLデータ(理想的には2Gb以上)を管理することです。メモリ管理に役立ち、ノードを検索する可能性を与えます。
サポートありがとうございます!
それは不可能だと言うすべての人のために:私は最近、質問をした後、「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を使用して毎日webappを作成しているとき、XSLT内で「// something」式を使用するたびに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ライセンスされているので、自由に試してみて、ニーズに合っているかどうかを確認してください。 (古いスクリーンで実行できるように十分なメモリ要件でHTMLスクリーンスクレイピングを行うために作成しました。Androidデバイス...)バグを見つけたら、それらをファイリングして知らせてください。 googlecodeサイトで!
遅い回答で申し訳ありませんが、SAXパーサーの 単純なXPath式 パスを実装しました。タグ、オプションの値を持つ属性、およびSAXのフォワードの性質によるインデックスのみをサポートします。ハンドラーが ExpressionFilter を実装するときに、指定された式を評価するために デリゲートハンドラー を作成しました。これらのクラスはプロジェクトに埋め込まれていますが、抽出するのは難しくありません。
例 -HandlerHtml
プレフィックスを持つクラスを参照
できることは、XSLトランスフォーマーをSAX入力ソースにフックすることです。処理はシーケンシャルに行われ、XSLプリプロセッサは、指定された結果に入力を調整するために入力をキャッチしようとします。これを使用して、パスの値をストリームから引き出すことができます。これは、1回のパスでさまざまなXPATH結果を生成する場合に特に便利です。
結果として(通常)XMLドキュメントを取得できますが、たとえば、StreamResult
から期待する出力をあまり手間をかけずに引き出すことができます。
Saxon-SA XSLT-processorのストリーミングモードをご覧ください。
http://www.saxonica.com/documentation/sourcedocs/serial.html
「パス式をストリーミングできるかどうかを決定するルールは次のとおりです。
Doc()またはドキュメントの呼び出しによって導入されるパス式は、次のように定義されたXPathのサブセットに準拠する必要があります。
xMLスキーマのID制約に表示されるパス式の規則に準拠している場合、XPath式はすべて受け入れられます。これらの規則では、述部は許可されません。最初のステップ(最初のステップのみ)に「//」を使用して導入できます。最後のステップでは、オプションで属性軸を使用できます。他のすべてのステップは、子軸を使用した単純な軸ステップでなければなりません。
式は、要素のみ、属性のみ、または要素と属性の混合を選択する必要があります。
単純なフィルター(1つ以上)もサポートされています。各フィルターは最後のステップまたは式全体に適用でき、コンテキストノード(self、child、attribute、descendant、descendant-or-self、またはnamespace軸)からの下方選択のみを使用する必要があります。位置であってはなりません(つまり、position()またはlast()を参照してはならず、数値であってはなりません。実際、コンパイル時にSaxonが数値ではないと判断できるようにする必要があります)。フィルターは、ユニオンまたはユニオンのブランチに適用できません。これらの条件に違反すると、ストリーミングの最適化なしで式が評価されます。
これらのルールは、他の最適化の書き換えが式に適用された後に適用されます。たとえば、一部のFLWOR式は、これらのルールを満たすパス式に書き換えられます。
最適化は、saxon:stream()拡張関数、XSLT xsl:copy-of命令のsaxon:read-once属性、またはXQueryプラグマsaxon:streamを使用して明示的に要求された場合にのみ有効になります。スタイルシートまたはクエリがSaxon-SAを使用して処理される場合にのみ使用できます。」
注:商用バージョンでは、この機能が利用可能です。私は以前にSaxonを広範囲に使用しましたが、これはすてきな作品です。
うーん、本当にあなたを理解しているかどうかわからない。私の知る限り、SAXモデルはイベント指向です。つまり、解析中に特定のノードが検出された場合、何かを実行します。ええ、それはメモリには良いのですが、XPathをどのように取り入れたいのかわかりません。 SAXはモデルを構築しないため、これが可能だとは思いません。
標準のjavax xpath APIは、技術的には既にストリームで機能します。 javax.xml.xpath.XPathExpression
はInputSource
に対して評価することができ、これはReader
で構成できます。私はそれがカバーの下でDOMを構築するとは思わない。
QuiXPath https://code.google.com/p/quixpath/ も試しましたか?