c - 使用 libxml2 的 XPath 在 XML 文档中查找命名空间节点时出现问题

标签 c xml xpath xml-parsing libxml2

鉴于以下文档,我想提取tns:EchoResponse。 (为了便于阅读,对原始文档进行了美化。)

<?xml version="1.0" encoding="UTF-8"?>
<soap:Envelope 
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
  xmlns:xsd="http://www.w3.org/2001/XMLSchema" 
  xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
    <soap:Body>
        <tns:EchoResponse 
          xmlns:tns="http://www.apis-it.hr/fin/2012/types/f73" 
          xsi:schemaLocation="http://www.apis-it.hr/fin/2012/types/f73 FiskalizacijaSchema.xsd "
          >
            hello
         </tns:EchoResponse>
    </soap:Body>
</soap:Envelope>

我已经解析了文档,创建了 XPath 上下文,注册了命名空间 soaptns,然后运行了查询使用以下 XPath 表达式。

//soap:Envelope[1]/soap:Body[1]/tns:EchoResponse[1]

不幸的是,只有忽略 namespace 并仅使用本地名称的查找似乎才有效:

//*[local-name(.) = 'Envelope']/*[local-name(.) = 'Body'][1]/*[local-name(.) = 'EchoResponse'][1]

那么...我做错了什么?我错误地假设了什么?这是处理此文档的代码片段。

    xmlDocPtr xmldoc = xmlReadMemory(databuffer, datasize, ISFEndpointURL(), NULL, 0);
    if(!xmldoc)
    {
        err = -1;
        goto finalize;
    }

    xmlXPathContextPtr xpathCtx = xmlXPathNewContext(xmldoc);
    if(!xpathCtx)
    {
        err = -1;
        xmlFreeDoc(xmldoc);
        goto finalize;
    }

    xmlXPathRegisterNs(xpathCtx, BAD_CAST "soap", BAD_CAST "http://schemas.xmlsoap.org/soap/envelope");
    xmlXPathRegisterNs(xpathCtx, BAD_CAST "tns", BAD_CAST "http://www.apis-it.hr/fin/2012/types/f73");

    // //soap:Envelope[1]/soap:Body[1]/*[local-name(.) = 'EchoResponse']
    xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression(BAD_CAST "./*[local-name(.) = 'Envelope']/*[local-name(.) = 'Body'][1]/*[local-name(.) = 'EchoResponse'][1]", xpathCtx);
    if(!xpathObj)
    {
        err = -1;
        xmlXPathFreeContext(xpathCtx);
        xmlFreeDoc(xmldoc);
        goto finalize;
    }
    if(xmlXPathNodeSetIsEmpty(xpathObj->nodesetval)){
        err = -1;
        xmlXPathFreeObject(xpathObj);
        xmlXPathFreeContext(xpathCtx);
        xmlFreeDoc(xmldoc);
        printf("%s: No XPath result\n", __FUNCTION__);
        goto finalize;
    }


    if(strcmp((char *)xmlXPathCastNodeSetToString(xpathObj->nodesetval), echoText))
    {
        err = 1;
        xmlXPathFreeObject(xpathObj);
        xmlXPathFreeContext(xpathCtx);
        xmlFreeDoc(xmldoc);
        printf("%s: Incorrect echo result: %s\n", __FUNCTION__, xpathObj->stringval);
        goto finalize;
    }

    xmlXPathFreeObject(xpathObj);
    xmlXPathFreeContext(xpathCtx);

最佳答案

XML 文档中的 soap 前缀绑定(bind)到命名空间 URI

http://schemas.xmlsoap.org/soap/envelope/

而您的代码将 XPath 上下文中的 soap 前缀绑定(bind)到不同的 URI

http://schemas.xmlsoap.org/soap/envelope

XPath 不匹配任何内容,因为它正在寻找错误的命名空间。

关于c - 使用 libxml2 的 XPath 在 XML 文档中查找命名空间节点时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14585111/

相关文章:

c - 无论我运行什么代码,意外标记 `(' 附近的语法错误

xml - 创建 XML 以导入 Excel,特别是日期

java - 为什么我的 Android 应用程序找不到 XML 文件中声明的 TextView 或按钮?

java - 设置xml编码

java - 如何仅使用属性来定位 Selenium 中的元素,而不管属性包含什么值

xpath - MarkLogic:Xpath与搜索

c - 斐波那契数列之和

c - C中基于事件的套接字编程

javascript - 使用 Emscripten Worker API 传输数据而不复制

c++ - 具有 XPath 和宽字符支持的最轻量级 XML 解析器