2011-01-27 7 views
3
でのXPathクエリの取得行/列

に我々はpugixmlでXPathクエリ結果の行/列を取得したい:Pugixml

pugi::xpath_query query_child(query_str); 
std::string value = Convert::toString(query_child.evaluate_string(root_node)); 

私たちは、オフセットではなく、行/列取得することができます。

unsigned int = query_child.result().offset; 

ファイルを再解析すると、offset =>(行、列)に変換できますが、効率的ではありません。

これを達成するために効率的なメソッドがありますか?

答えて

2
  1. result()。offsetは、クエリ文字列の最後の解析されたオフセットです。クエリが正常に解析された場合は0になります。これはXMLファイルのオフセットではありません。

  2. 文字列を返すXPathクエリでは、 'XMLファイル内のオフセット'の概念が定義されていません。つまり、concat("a", "b")クエリの期待値は?

  3. ノードを返すXPathクエリでは、ファイル内のノードデータのオフセットを取得できます。残念なことに、解析パフォーマンスとメモリ消費の理由から、この情報は再解析せずに取得することはできません。 TODOリストには、いくつかのコード行を使用して簡単にするためのタスクがありますが、しばらく時間がかかります。

だから、あなたはXPathクエリの結果であるノードのオフセットを見つけたいと仮定すると、唯一の方法は、(ノードセット(query.evaluate_node_setまたはnode.select_single_node/select_nodes)、オフセット取得としてXPathクエリの結果を得るためにnode.offset_debug()です)、それを手動で行/列に変換します。

オフセット - >行/列変換のデータ構造を1回準備してから、複数回使用することができます。たとえば、次のコードが動作するはずです:

#include <vector> 
#include <algorithm> 
#include <cassert> 
#include <cstdio> 

typedef std::vector<ptrdiff_t> offset_data_t; 

bool build_offset_data(offset_data_t& result, const char* file) 
{ 
    FILE* f = fopen(file, "rb"); 
    if (!f) return false; 

    ptrdiff_t offset = 0; 

    char buffer[1024]; 
    size_t size; 

    while ((size = fread(buffer, 1, sizeof(buffer), f)) > 0) 
    { 
     for (size_t i = 0; i < size; ++i) 
      if (buffer[i] == '\n') 
       result.push_back(offset + i); 

     offset += size; 
    } 

    fclose(f); 

    return true; 
} 

std::pair<int, int> get_location(const offset_data_t& data, ptrdiff_t offset) 
{ 
    offset_data_t::const_iterator it = std::lower_bound(data.begin(), data.end(), offset); 
    size_t index = it - data.begin(); 

    return std::make_pair(1 + index, index == 0 ? offset : offset - data[index - 1]); 
} 

これはMacスタイルの改行を処理せず、タブも処理しません。もちろんこれは簡単に追加することができます。

+0

ありがとうございます、はいノードのオフセットを見つけたいと思います。 しかし、問題は再解析せずに行/列に変換する方法ですか? おそらく私はpugixmlコードを編集する必要がありますか? –

+0

答えは - あなたはできません。 pugixmlコードを編集することはできますが、これはあまり簡単ではありません。パフォーマンス上の理由から、レクサーがないため、改行を数えることのできる場所は1つではありません。あなたの最善の策は再解析です。一回のパスを一度に再解析して、キー=改行オフセットと値=行インデックス(増加番号)のstd :: map を作成します。 equal_rangeを使用してオフセットをrow + columnに変換することができます。 pugixmlコードを変更する必要はありません。 – zeuxcg

+0

サンプルコードを使って答えを更新しました。 – zeuxcg