2009-06-15 9 views
13

提供されたxml-documentに対するストリーミングXPath式の評価用の実稼働可能なライブラリはありますか?私の調査によると、既存のソリューションのほとんどは、xpath表現を評価する前にDOMツリー全体をメモリにロードしています。ストリーミングXPath評価

+1

VTD-XMLはDOM上に構築されていないだけのXPathをサポートしている、それはより多くのメモリが効率的です... –

+0

たくさんThaks、私は前にあなたのプロジェクトを見てきました。有望に見える – nixau

+0

このテーマに関するいくつかの新しい情報があります - 私の答えを見てください。 –

答えて

3

これは、XPath構文をすることができますことを考えると、完全なXPathの実装のための実用的な次のようになります。

/AAA/XXX/following::* 

/AAA/BBB/following-sibling::* 

先読み要件を意味していますか?とにかく残りの文書をロードする必要がある特定のノードからのものです。

Nuxライブラリ(具体StreamingPathFilter)のためのDOCは、この点になり、およびXPathのサブセットに依存しているいくつかの実施例を参照します。 Nuxはいくつかのストリーミングクエリ機能を実行すると主張していますが、上記を考慮すると、XPath実装に関していくつかの制限があります。

+0

実際には、検証の目的で、指定されたxmlドキュメントのいくつかのノードをチェックする簡単なxpathクエリを実行する必要があります。 XML文書はエンティティを表し、そのノードのいくつかは他のエンティティへの外部キーを格納します。その結果、これらの特別なノードに何らかの間接検証を再度適用する必要があります。全体の文書はかなり大きく、いくつかの単純なxpath照会の実行のために、そのような大量のデータをメモリーに格納することは不十分です。 – nixau

+1

Nuxライブラリがこのシナリオであなたを助けることができるようです。あるいは、Staxライブラリを使用して、特定のノードから取得するローカルXMLドキュメントにXPathを適用できますか? –

+0

実際には、xmlドキュメントの構造が比較的単純であり、ドキュメントの特定のノードを取り除き、それに対してxpath式を評価するために意味がないため、第2のアプローチを採用することはできません。 – nixau

3

いくつかのオプションがあります:

  • DataDirect Technologies sells an XQuery implementation可能、投影とストリーミングを採用しています。ファイルをマルチギガバイトの範囲で扱うことができます。利用可能なメモリよりも大きい。これはスレッドセーフなライブラリなので、簡単に統合できます。 Javaのみ。

  • Saxonは、オープンソースのバージョンであり、より高価なより高価ないとこがあり、一部の状況でストリーミングを行います。 Javaが、.netポートもあります。

  • MarkLogicおよびeXistは、XMLがロードされている場合、XPathをかなりインテリジェントに処理するXMLデータベースです。

0

FWIW、私は非常に大規模な(> 3ギガバイト)のファイルに対するフィルタXPathクエリをストリーミング木の実を使用しました、そして、それは両方完璧に働いて、非常に少ないメモリを使用しています。私のユースケースは少し異なります(検証中心ではありません)。しかし、Nuxを使ってそれを試してみることを強くお勧めします。

1

実際の経験はありませんが、QuiXProc(http://code.google.com/p/quixproc/)に言及する価値はあると思いました。これはXProcへのストリーミングアプローチであり、XPathのストリーミングサポートを提供するライブラリを使用しています。

0

私はカスタムコードを書くつもりです。 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();