2

我想使用 POCO 的库提取单个节点,但不知道该怎么做。我是 XML 新手。

XML 本身看起来像这样(缩写):

<?xml version="1.0" encoding="UTF-8"?>
<!-- Created by XMLPrettyPrinter on 11/28/2012 from  -->
<sbml xmlns = "http://www.sbml.org/sbml/level2/version4" level = "2" version = "4">
<model id = "cell">
  <listOfSpecies>
</listOfSpecies>
  <listOfParameters>
     <parameter id = "kk1" value = "1"/>
  </listOfParameters>
  <listOfReactions>
     <reaction id = "J1" reversible = "false">
... much stuff here ..
  </listOfReactions>
</model>
</sbml>

我想提取 listOfReactions 节点中的所有内容并将其存储在 std::string 中,以便以后进行 MD5 散列。

我试过这个:

ifstream in(JoinPath(gTestDataFolder, "Test_1.xml").c_str());
InputSource src(in);
DOMParser parser;
AutoPtr<Document> pDoc = parser.parse(&src);
NodeIterator it(pDoc, Poco::XML::NodeFilter::SHOW_ALL);
Node* pNode = it.nextNode();

while(pNode)
{
    clog<<pNode->nodeName()<<endl;
    string elementID = "listOfReactions";
    if(pNode->nodeName() == "listOfReactions")
    {
         //Extract everything in this node... how???
    }

    pNode = it.nextNode();
}
4

4 回答 4

5

我自己也遇到了类似的问题。例如,在应用了“Poco::XML::NodeFilter::SHOW_ALL”过滤器的情况下,遍历 XML 文档时将包括所有节点类型(元素、文本、CDataSection 等)。我发现 POCO 不包含从“NextNode()”返回的每个节点中的所有数据。

如果想要访问 XML 节点的属性,首先必须使用“hasAttributes()”查询节点以检查它是否具有任何属性,然后如果有,则遍历这些属性中的每一个以找到感兴趣的属性。

XML 示例:

<?xml version="1.0"?>
<reaction id="J1" reversible="false">

C++ 示例:

...
Poco::XML::NamedNodeMap* attributes = NULL;
Poco::XML::Node* attribute = NULL;

while(pNode)
{
 if( (pNode->nodeName() == "reaction") && pNode->hasAttributes())
 {
   attributes = pNode->attributes(); 
   for(unsigned int i = 0; i < attributes->length(); i++)
   {
     attribute = attributes->item(i);
     cout << attribute->nodeName() << " : " << attribute->nodeValue() << endl
   }
  }
  pNode = it.nextNode();
}
...

应该输出:

id : J1
reversible : false

如果想要访问两个 XML 标记之间的文本,如下面的 XML 示例所示,首先必须找到名称与感兴趣的标记匹配的节点,就像您在示例中所做的那样,然后检查下一个通过调用“NextNode()”来查看该节点是否具有节点名称“#text”或“#cdata-section”。如果是这种情况,则此“下一个节点”的值将包含 XML 标记之间的文本。

XML 示例:

<?xml version="1.0"?>
<listOfReactions>Some text</listOfReactions>

C++ 示例:

...
while(pNode)
{
 if(pNode->nodeName() == "listOfReactions")
 {
   pNode = it.nextNode();
   if(pNode->nodeName() != "#text")
   {
     continue; //No text node present
   }
   cout << "Tag Text: " << pNode->nodeValue() << endl;
  }
  pNode = it.nextNode();
}
...

应该输出:

Some text
于 2013-06-25T20:11:06.513 回答
0

试试这些幻灯片,以及 API 参考的Poco 文档

这里还有一个很好的教程,其中有一个简单易懂的示例,说明您正在尝试做什么。

于 2013-03-25T22:35:35.553 回答
0

游戏迟到了,但也许仍然有用。我正在研究 Poco XML 以提取以 xml 传递的天气数据。我发现@JBently 提到的 PDF 幻灯片是一个很好的介绍。这提供了 hpp 文件。这个例子涵盖了实现。我省略了 LexicalHandler。

我查看字符串 listOfReactions,当找到时,我将属性名称和值添加到 startElement() 中的字符串。在 characters() 中,我将节点中的文本添加到字符串中,并将其添加到可以遍历的向量中。

输出:

id=J1,reversible=false,false move
id=J2,reversible=true,true move

我稍微更改了您的 xml 以进行测试,并转义了双引号以在程序中使用。

<?xml version=\"1.0\" encoding=\"UTF-8\"?><sbml xmlns = \"http://www.sbml.org/sbml/level2/version4\" level = \"2\" version = \"4\">
    <model id = \"cell\">
        <listOfSpecies>species</listOfSpecies>
        <listOfParameters>
            <parameter id = \"kk1\" value = \"1\"/>
        </listOfParameters>
        <listOfReactions>
            <reaction id = \"J1\" reversible = \"false\">false move</reaction>
            <reaction id = \"J2\" reversible = \"true\">true move</reaction>
        </listOfReactions>
    </model>
</sbml>

主要的:

#include <iostream>

#include "MyHandler.hpp"

using namespace std;

int main() {
    auto s = {XML file from above};
    MyHandler handler {};
    Poco::XML::SAXParser parser {};
    parser.setFeature(Poco::XML::XMLReader::FEATURE_NAMESPACES, false);
    parser.setFeature(Poco::XML::XMLReader::FEATURE_NAMESPACE_PREFIXES, true);
    parser.setContentHandler(&handler);

    try {
        parser.parseString(s);
    } catch (Poco::Exception& e) {
        cerr << e.displayText() << endl;
    }
    auto saved = handler.saved_reactions();
    for (auto& i : saved) {
        cout << i << endl;
    }
    return 0;
}

MyHandler.hpp:

#ifndef MYHANDLER_HPP_
#define MYHANDLER_HPP_

#include <iostream>
#include <vector>
#include <Poco/SAX/Attributes.h>
#include <Poco/SAX/ContentHandler.h>
#include <Poco/SAX/SAXParser.h>

class MyHandler: public Poco::XML::ContentHandler {
public:
    MyHandler();
    virtual ~MyHandler();

    // ContentHandler overrides, begin.
    void setDocumentLocator(const Poco::XML::Locator* loc);
    void startDocument();
    void endDocument();
    void startElement(
            const Poco::XML::XMLString&,
            const Poco::XML::XMLString&,
            const Poco::XML::XMLString&,
            const Poco::XML::Attributes&);
    void endElement(
            const Poco::XML::XMLString&,
            const Poco::XML::XMLString&,
            const Poco::XML::XMLString&);
    void characters(const Poco::XML::XMLChar ch[], int, int);
    void ignorableWhitespace(const Poco::XML::XMLChar ch[], int, int);
    void processingInstruction(const Poco::XML::XMLString&, const Poco::XML::XMLString&);
    void startPrefixMapping(const Poco::XML::XMLString&, const Poco::XML::XMLString&);
    void endPrefixMapping(const Poco::XML::XMLString&);
    void skippedEntity(const Poco::XML::XMLString&);
    // ContentHandler overrides, end
    std::vector<std::string> saved_reactions();

private:
    bool show = false;
    std::string reactions_s {};
    std::vector<std::string> reactions_v {};
};

#endif /* MYHANDLER_HPP_ */

MyHandler.cpp:

#include "MyHandler.hpp"

MyHandler::MyHandler() {}
MyHandler::~MyHandler() {}

void MyHandler::setDocumentLocator(const Poco::XML::Locator* loc) {
}

void MyHandler::startDocument() {
}

void MyHandler::endDocument() {
}

void MyHandler::startElement(const Poco::XML::XMLString& namespaceURI, const Poco::XML::XMLString& localName, const Poco::XML::XMLString& qname, const Poco::XML::Attributes& attributes) {
    int x {0};
    std::cout << "qname: " << qname << std::endl;
    /*    std::cout << "getValue(): " << attributes.getValue(qname) << std::endl;
    std::cout << "getLength(): " << attributes.getLength() << std::endl;*/
    if (qname == "listOfReactions") {
        show = true;
    }
    if (show) {
        if (attributes.getLength()) {
            reactions_s.clear();
            x = attributes.getLength();
            for (int i = 0; i < x; ++i) {
                std::cout << "getQName(): " << attributes.getQName(i) << ", getValue(): " << attributes.getValue(i) << std::endl;
                if (reactions_s.size()) reactions_s += ",";
                reactions_s += attributes.getQName(i) + "=" + attributes.getValue(i);
            }
        }
    }
}

void MyHandler::endElement(const Poco::XML::XMLString& allocator,
        const Poco::XML::XMLString& allocator1,
        const Poco::XML::XMLString& allocator2) {
}

void MyHandler::characters(const Poco::XML::XMLChar ch[], int start, int length) {
    std::cout << std::string(ch + start, length) << std::endl;
    if (show) {
        reactions_s += "," + std::string(ch + start, length);
        reactions_v.emplace_back(reactions_s);
    }
}

void MyHandler::ignorableWhitespace(const Poco::XML::XMLChar ch[], int start, int length) {
}

void MyHandler::processingInstruction(const Poco::XML::XMLString& allocator, const Poco::XML::XMLString& allocator1) {
}

void MyHandler::startPrefixMapping(const Poco::XML::XMLString& allocator, const Poco::XML::XMLString& allocator1) {
}

void MyHandler::endPrefixMapping(const Poco::XML::XMLString& allocator) {
}

std::vector<std::string> MyHandler::saved_reactions() {
    return reactions_v;
}

void MyHandler::skippedEntity(const Poco::XML::XMLString& allocator) {
}
于 2016-03-10T12:55:10.973 回答
-1

假设 XML 在文件“hello.xml”中

<root>
    <headers>
        <header>Hello</header>
        <header>World</header>
    </headers>
</root>

可以这样解析:-

#include <string>
#include <sstream>
#include <Poco/Exception.h>
#include <Poco/AutoPtr.h>
#include <Poco/Util/XMLConfiguration.h>

using namespace std;
using namespace Poco;
using namespace Poco::Util;

int main(int argc, char*argv[]) {

    int counter = 0;
    AutoPtr apXmlConf(new XMLConfiuration("hello.xml"));
    try {
        while(1) { // Loop breaks by Poco exception
            stringstream tag;
            tag << "headers.header[" << counter++ << "]";
            string header = apXmlConf->getString(tag.str());
            cout << header << " ";
        }
    } catch(NotFoundException& e) { (void)e; }
    cout << endl;
    return 0;
}

希望有帮助。

于 2014-09-06T14:58:54.287 回答