5

我为 libxml2 编写了一个 C++ 包装函数,使我可以轻松地对 XML 文档进行查询:

bool XPathQuery(
    const std::string& doc,
    const std::string& query,
    XPathResults& results); 

但是我有一个问题:我需要能够对我的第一个查询的结果进行另一个 XPath 查询。

目前我通过将整个子文档存储在我的 XPathResult 对象中来做到这一点,然后我将 XPathResult.subdoc 传递给 XPathQuery 函数。这是非常低效的。

所以我想知道...... libxml2 是否提供任何可以轻松存储 xpath 查询的上下文(可能是对节点的引用?)然后使用该引用作为 xpath 根执行另一个查询的东西?

4

1 回答 1

6

您应该重复使用xmlXPathContext并更改其node成员。

#include <stdio.h>
#include <libxml/xpath.h>
#include <libxml/xmlerror.h>

static xmlChar buffer[] = 
"<?xml version=\"1.0\"?>\n<foo><bar><baz/></bar></foo>\n";

int
main()
{
  const char *expr = "/foo";

  xmlDocPtr document = xmlReadDoc(buffer,NULL,NULL,XML_PARSE_COMPACT);
  xmlXPathContextPtr ctx = xmlXPathNewContext(document);
  //ctx->node = xmlDocGetRootElement(document);

  xmlXPathCompExprPtr p = xmlXPathCtxtCompile(ctx, (xmlChar *)expr);
  xmlXPathObjectPtr res = xmlXPathCompiledEval(p, ctx);

  if (XPATH_NODESET != res->type)
    return 1;

  fprintf(stderr, "Got object from first query:\n");
  xmlXPathDebugDumpObject(stdout, res, 0);
  xmlNodeSetPtr ns = res->nodesetval;
  if (!ns->nodeNr)
    return 1;
  ctx->node = ns->nodeTab[0];
  xmlXPathFreeObject(res);

  expr = "bar/baz";
  p = xmlXPathCtxtCompile(ctx, (xmlChar *)expr);
  res = xmlXPathCompiledEval(p, ctx);

  if (XPATH_NODESET != res->type)
    return 1;
  ns = res->nodesetval;
  if (!ns->nodeNr)
    return 1;
  fprintf(stderr, "Got object from second query:\n");
  xmlXPathDebugDumpObject(stdout, res, 0);

  xmlXPathFreeContext(ctx);
  return 0;
}
于 2009-12-04T04:51:14.200 回答