简体   繁体   English

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

[英]How to use XPath in XMLReader API of libxml2?

The tutorial here says we can used XPath in XMLReader API if we expand the current node and set it to be the context node of the xmlXPathContext object. 这里的教程说,如果我们扩展当前节点并将其设置为xmlXPathContext对象的上下文节点,则可以在XMLReader API中使用XPath。 Unfortunately, the example the tutorial provides is in Python, which language I don't understand at all. 不幸的是,本教程提供的示例是使用Python编写的,我完全不懂这种语言。 I tried to create my own example in C++, but got stuck. 我试图在C ++中创建自己的示例,但遇到了麻烦。 The problem is function xmlXPathSetContextNode always fails. 问题是函数xmlXPathSetContextNode总是失败。 Below is my codes and a XML document to be read by the example application. 下面是示例应用程序将读取的我的代码和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;
}

The contents of the XML document is 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>

Any hint will be appreciated. 任何提示将不胜感激。 Thanks in advance. 提前致谢。 m(_ _)m m(_ _)m

Problem solved. 问题解决了。 function xmlTextReaderCurrentDoc shall not be called before any xmlTextReaderRead . 功能xmlTextReaderCurrentDoc不得任何之前调用xmlTextReaderRead I shall have checked the return value of xmlTextReaderCurrentDoc . 我将检查xmlTextReaderCurrentDoc的返回值。 In the above buggy codes, it returns NULL . 在上面的错误代码中,它返回NULL Consequently, no valid XPath context can be obtained. 因此,无法获得有效的XPath上下文。 The official document doesn't mention when is the right time to invoke xmlTextReaderCurrentDoc , so I'll leave this q&a here for other people who encounter the same problem to google. 官方文档没有提到何时才是调用xmlTextReaderCurrentDoc的正确时间,因此我将在这里为其他遇到相同问题的人提供此xmlTextReaderCurrentDoc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM