3

我们想在 pugixml 中获取 xpath 查询结果的行/列:

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 => (line, column),但效率不高。

有没有一种有效的方法来实现这一目标?

4

1 回答 1

2
  1. result().offset 是查询字符串中最后解析的偏移量;如果查询成功解析,它将等于 0;所以这不是 XML 文件中的偏移量。

  2. 对于返回字符串的 XPath 查询,未定义“XML 文件中的偏移量”的概念——即您希望concat("a", "b")查询什么?

  3. 对于返回节点的 XPath 查询,您可以获取文件中节点数据的偏移量。不幸的是,由于解析性能和内存消耗的原因,不重新解析就无法获得这些信息。TODO 列表中有一个任务可以使它更容易(即用几行代码),但这需要一段时间。

因此,假设您要查找作为 XPath 查询结果的节点的偏移量,唯一的方法是将 XPath 查询结果作为节点集(query.evaluate_node_setnode.select_single_node/select_nodes)获取,获取偏移量(node.offset_debug())并手动将其转换为行/列。

可以为offset -> line/column转换准备一个数据结构一次,然后多次使用;例如,以下代码应该可以工作:

#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 风格的换行符,也不处理制表符;当然,这可以简单地添加。

于 2011-01-27T15:37:44.073 回答