c++ - 如何在 libxml2 的 XMLReader API 中使用 XPath?

标签 c++ xml xpath libxml2

教程here表示如果我们展开当前节点并将其设置为 xmlXPathContext 对象的上下文节点,我们就可以在 XMLReader API 中使用 XPath。不幸的是,教程提供的示例是用 Python 编写的,我根本不懂这种语言。我试图用 C++ 创建自己的示例,但卡住了。问题是函数 xmlXPathSetContextNode 总是失败。下面是我的代码和示例应用程序要读取的 XML 文档。

// BUILD: g++ thisFile.cpp -std=c++11 -Wall $(xml2-config --cflags --libs)
#include <cstdio> // for function fopen, fseek, rewind, fread and fclose
#include <libxml/xmlreader.h> // for data type xmlTextReader
#include <libxml/xpath.h> // for data type xmlXPathContext
#include <memory> // for class template shared_ptr
#include <stdexcept> // for class runtime_error;
#define _X(s) ((const xmlChar *)s)
int main(int argc, char *argv[])
{
    using std::shared_ptr;
    // Create a text reader.
    shared_ptr<xmlTextReader> reader(::xmlReaderForFile("sample.xml", NULL, 0), &::xmlFreeTextReader);
    // Create a XPath context.
    xmlDocPtr doc = ::xmlTextReaderCurrentDoc(reader.get());
    shared_ptr<xmlXPathContext> ctxt(::xmlXPathNewContext(doc), &::xmlXPathFreeContext);
    // Use the text reader to read the stream.
    int ret;
    try {
        while ((ret = ::xmlTextReaderRead(reader.get())) == 1) {
            // Ignore all nodes except <storyinfo>.
#if 0
            xmlNodePtr node = ::xmlTextReaderCurrentNode(reader.get());
#else
            xmlNodePtr node = ::xmlTextReaderExpand(reader.get());
#endif
            if (::xmlStrncmp(node->name, _X("storyinfo"), 10) != 0) continue;
            // Set the current node as the context node.
            ::printf("node: 0x%08X\n", (size_t)node);
            if (::xmlXPathSetContextNode(node, ctxt.get()) == -1) {
                ::fprintf(stderr, "ERROR(%d): %s\n", ctxt->lastError.code, ctxt->lastError.message);
                throw std::runtime_error("err_xpath_set_context");
            }
            // Use a XPath to find <datewritten>.
            shared_ptr<xmlXPathObject> xpathFound(::xmlXPathEvalExpression(_X("datewritten"), ctxt.get()), &::xmlXPathFreeObject);
            if (xmlXPathNodeSetGetLength(xpathFound->nodesetval) == 0) throw std::runtime_error("err_xpath_not_fonud");
            shared_ptr<xmlChar> zTextContent(::xmlXPathCastToString(xpathFound.get()), ::xmlFree);
            ::printf("found: %s\n", zTextContent.get());
            break;
        }
        if (ret == -1) {
            ::fprintf(stderr, "ERROR: %s\n", "xmlTextReaderRead failure!");
            return 1;
        }
    }
    catch (const std::runtime_error& e) {
        ::fprintf(stderr, "ERROR: %s\n", e.what());
    }
    // Exit the program.
    return 0;
}

XML文档的内容是

<?xml version="1.0"?>
<story>
    <storyinfo>
        <author>John Fleck</author>
        <datewritten>June 2, 2002</datewritten>
        <keyword>example keyword</keyword>
    </storyinfo>
    <body>
        <headline>This is the headline</headline>
        <para>This is the body text.</para>
    </body>
</story>

任何提示将不胜感激。提前致谢。 m(_ _)m

最佳答案

问题解决了。函数 xmlTextReaderCurrentDoc 不应在任何 xmlTextReaderRead 之前调用。我应该已经检查了 xmlTextReaderCurrentDoc 的返回值。在上面的错误代码中,它返回 NULL。因此,无法获得有效的 XPath 上下文。官方文档没有提到什么时候调用xmlTextReaderCurrentDoc,所以我把这个问答留给遇到同样问题的其他人去google。

关于c++ - 如何在 libxml2 的 XMLReader API 中使用 XPath?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26137480/

相关文章:

c++ - 为什么 VAO 可以在不绑定(bind)的情况下使用 VBO 数据?

c++ - 在 STL 容器中发布 opencv 图像?

c++ - Qt问题将参数传递给插槽

javascript - 无法使用javascript获取描述RSS标签数据

Java - 下载和发送文件

xpath - 为什么需要//而不是/

JavaScript - 提取文档元字段的最快方法

c++ - 如何正确声明自引用模板类型?

xpath - 当一些 child 存在时选择 CDATA 内容的 xpath

xml - XML中的 "xmlns"是什么意思?