使用libxml2在xml文件中查找节点

时间:2012-10-23 00:05:19

标签: c xml-parsing libxml2

我正在尝试编写一个函数,该函数将在xml文件中找到具有指定名称的节点。 问题是该函数永远不会找到指定的节点。

xmlNodePtr findNodeByName(xmlNodePtr rootnode, const xmlChar * nodename)
{
    xmlNodePtr node = rootnode;
    if(node == NULL){
        log_err("Document is empty!");
        return NULL;
    }

    while(node != NULL){

        if(!xmlStrcmp(node->name, nodename)){
            return node; 
        }
        else if(node->children != NULL){
            node = node->children; 
            xmlNodePtr intNode =  findNodeByName(node, nodename); 
            if(intNode != NULL){
                return intNode;
            }
        }
        node = node->next;
    }
    return NULL;
}

我可以在调试器中看到函数确实深入到子节点但仍然返回NULL。

提前致谢。

3 个答案:

答案 0 :(得分:8)

else if(node->children != NULL) {
    node = node->children; 
    xmlNodePtr intNode =  findNodeByName(node, nodename); 
    if (intNode != NULL) {
        return intNode;
    }
}

这应该是:

else if (node->children != NULL) {
    xmlNodePtr intNode =  findNodeByName(node->children, nodename); 
    if(intNode != NULL) {
        return intNode;
    }
}

并且工作正常

答案 1 :(得分:4)

你的功能是正确的。添加调试行以查看它在您的情况下不起作用的原因。例如:

    printf("xmlStrcmp(%s, %s)==%d\n", node->name, nodename,
        xmlStrcmp(node->name, nodename));

但你真的不需要那个功能。您可以使用xmlXPathEval

答案 2 :(得分:-1)

当@jarekczek提到XPath时,他意味着使用XPath而不是你的功能。

使用XPath,您的功能将变为:

xmlNodeSetPtr findNodesByName(xmlDocPtr doc, xmlNodePtr rootnode, const xmlChar* nodename) {
    // Create xpath evaluation context
    xmlXPathContextPtr xpathCtx = xmlXPathNewContext(doc);
    if(xpathCtx == NULL) {
        fprintf(stderr,"Error: unable to create new XPath context\n");
        return NULL;
    }

    // The prefix './/' means the nodes will be selected from the current node
    const xmlChar* xpathExpr = xmlStrncatNew(".//", nodename, -1);
    xmlXPathObjectPtr xpathObj = xmlXPathNodeEval(rootnode, xpathExpr, xpathCtx);
    if(xpathObj == NULL) {
        fprintf(stderr,"Error: unable to evaluate xpath expression \"%s\"\n", xpathExpr);
        xmlXPathFreeContext(xpathCtx);
        return NULL;
    }

    xmlXPathFreeContext(xpathCtx);

    return xpathObj->nodesetval;
}

注意:此函数返回与'nodename'匹配的所有节点。如果您只想要第一个节点,则可以将return xpathObj->nodesetval;替换为:

if (xpathObj->nodesetval->nodeNr > 0) {
    return xpathObj->nodesetval->nodeTab[0];
} else {
    return NULL;
}

您还可以将[1]附加到XPath查询以优化查询。