ストリーミング XPath の評価
-
13-09-2019 - |
質問
提供された XML ドキュメントに対する XPath 式の評価をストリーミングするための、実稼働対応のライブラリはありますか?私の調査によると、既存のソリューションのほとんどは、xpath 式を評価する前に DOM ツリー全体をメモリにロードします。
解決
XPath 構文で次のことが可能であることを考慮すると、これは完全な XPath 実装にとって実用的でしょうか。
/AAA/XXX/following::*
そして
/AAA/BBB/following-sibling::*
これは先読み要件を意味しますか?つまり特定のノードからは、とにかくドキュメントの残りの部分をロードする必要があります。
のドキュメント ナックス ライブラリ(特に ストリーミングパスフィルター) この点を指摘し、に依存するいくつかの実装を参照しています。 サブセット XPathの。Nux は、ストリーミング クエリ機能を実行すると主張していますが、上記を考慮すると、XPath の実装に関していくつかの制限があるでしょう。
他のヒント
いくつかのオプションがあります。
DataDirect Technologies は XQuery 実装を販売しています 可能な場合は投影とストリーミングを使用します。数ギガバイトの範囲のファイルを処理できます。利用可能なメモリを超えています。スレッドセーフなライブラリなので、統合が簡単です。Java のみ。
サクソン これはオープンソース バージョンであり、いくつかの状況でストリーミングを行う、控えめな価格のより高価なバージョンです。Java ですが、.net ポートもあります。
マークロジック そして 存在する XML データベースは、XML がロードされると、かなりインテリジェントな方法で XPath を処理します。
試してみてください Joostののます。
が、私はそれがQuiXProc言及する価値があると思った(ます。http:// code.google.com/p/quixproc/する)。それはXPROCにストリーミングアプローチであり、そして
..とりわけXPathのためのストリーミングのサポートを提供するライブラリを使用していますFWIW、私は非常に大規模な(> 3ギガバイト)のファイルに対するフィルタXPathクエリをストリーミング木の実を使用しました、そして、それは両方完璧に働いて、非常に少ないメモリを使用しています。私のユースケースは、(中心の検証ではない)、わずかに異なっていますが、私は非常にそれを木の実で打撃を与えることをお勧めしたい。
私は、カスタムコードのために行くと思います。 1だけで、XML文書の一部のパスを読みたい場合は、.NETライブラリは、非常に近いターゲットに私たちを取得します。
私がこれまで見のみのXPathのサブセットを尊重し、すべてのソリューションので、これはまた、溶液のこの種です。サブセットは、しかし、本当に小さいです。 :)
このC#コードは、XMLファイルを読み込み、明示的な経路指定されたノードをカウントします。またxr["attrName"]
構文を使用して、簡単に属性を操作することができます。
int c = 0;
var r = new System.IO.StreamReader(asArgs[1]);
var se = new System.Xml.XmlReaderSettings();
var xr = System.Xml.XmlReader.Create(r, se);
var lstPath = new System.Collections.Generic.List<String>();
var sbPath = new System.Text.StringBuilder();
while (xr.Read()) {
//Console.WriteLine("type " + xr.NodeType);
if (xr.NodeType == System.Xml.XmlNodeType.Element) {
lstPath.Add(xr.Name);
}
// It takes some time. If 1 unit is time needed for parsing the file,
// then this takes about 1.0.
sbPath.Clear();
foreach(object n in lstPath) {
sbPath.Append('/');
sbPath.Append(n);
}
// This takes about 0.6 time units.
string sPath = sbPath.ToString();
if (xr.NodeType == System.Xml.XmlNodeType.EndElement
|| xr.IsEmptyElement) {
if (xr.Name == "someElement" && lstPath[0] == "main")
c++;
// And test simple XPath explicitly:
// if (sPath == "/main/someElement")
}
if (xr.NodeType == System.Xml.XmlNodeType.EndElement
|| xr.IsEmptyElement) {
lstPath.RemoveAt(lstPath.Count - 1);
}
}
xr.Close();