我为libxml2编写了一个C++包装器函数,这使我可以轻松地对XML文档进行查询:
bool XPathQuery(
const std::string& doc,
const std::string& query,
XPathResults& results);
Run Code Online (Sandbox Code Playgroud)
但我有一个问题:我需要能够对我的第一个查询的结果进行另一个XPath查询.
目前我通过将整个子文档存储在我的XPathResult对象中来完成此操作,然后将XPathResult.subdoc传递给XPathQuery函数.这非常低效.
所以我想知道... libxml2提供了什么能够轻松存储xpath查询的上下文(可能是对节点的引用?)然后使用该引用作为xpath根执行另一个查询?
您应该重复使用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;
}
Run Code Online (Sandbox Code Playgroud)