result().offset は、クエリ文字列で最後に解析されたオフセットです。クエリが正常に解析された場合は 0 になります。したがって、これは XML ファイルのオフセットではありません。
文字列を返す XPath クエリの場合、'XML ファイルのオフセット' の概念は定義されていません。つまり、クエリに何を期待しconcat("a", "b")
ますか?
ノードを返す XPath クエリの場合、ファイル内のノード データのオフセットを取得できます。残念ながら、解析のパフォーマンスとメモリ消費の理由により、この情報は再解析しないと取得できません。TODO リストには簡単にするためのタスクがありますが (つまり、数行のコードで)、しばらく時間がかかります。
したがって、XPath クエリの結果であるノードのオフセットを見つけたいとすると、XPath クエリの結果をノード セットとして取得し (query.evaluate_node_set
またはnode.select_single_node/select_nodes
)、オフセットを取得し ( node.offset_debug()
)、手動で行/列に変換するしかありません。
オフセット -> 行/列変換用のデータ構造を一度準備すれば、それを複数回使用できます。たとえば、次のコードは機能するはずです。
#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 スタイルの改行を処理せず、タブを処理しません。もちろん、これは簡単に追加できます。