2009-11-05 78 views
4

我写了一个C++的libxml2的包装功能,可以很容易为我做的对XML文档的查询:使用libxml2执行递归XPath查询的最有效方法是什么?

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

但是我有一个问题:我需要能够在做其他的XPath查询我的第一个查询的结果。

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

所以我想知道... libxml2提供的任何内容可以很容易地存储xpath查询(对节点的引用,也许是?)的上下文,然后使用该引用执行另一个查询作为xpath根?

回答

5

您应该重复使用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; 
} 
+0

此测试程序崩溃我,当它试图debugprint的xmlxpath对象: xmlXPathDebugDumpObject(标准输出,RES,0); 我会看看我是否无法弄清楚发生了什么... – 2009-12-14 15:45:45

+0

看起来它与我如何构建或链接libxml2.dll有关。奇怪的。无论如何,解决它。 – 2009-12-14 16:48:37

+0

这就是我一直在寻找的东西。谢谢。 =) – 2009-12-14 16:49:29

相关问题