2013-03-25 17 views
2

我想使用POCO的庫提取一個單獨的節點,但無法弄清楚如何去做。我是XML新手。如何使用POCO解析xml文件並將特定節點提取到std :: string?

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 ::字符串後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(); 
} 
+2

那麼,你嘗試過什麼? – Alon 2013-03-25 22:30:21

+0

我試過他們的例子,涉及到一個DOM解析器。我能夠到達節點,但不知道是否會提取其內容。我可以打印pNode-> getNodeValue(),但不會打印任何內容。 – 2013-03-25 22:34:00

+0

節點「listOfReactions」不包含該值。它有一個名爲「#text」的子節點,其中包含值。這並不明顯,但是在執行「pNode-> firstNode() - > nodeValue()」時,您將獲得該值。 – 2017-01-20 15:09:47

回答

0

嘗試these slides,和Poco documentation的API參考。

還有一個不錯的tutorial here它有一個簡單明瞭的例子,你正在嘗試做什麼。

+0

已經看過所有這些。沒有解釋如何做這個簡單的事情。 – 2013-03-25 22:38:54

+0

@Totte請參閱編輯和教程鏈接。 – JBentley 2013-03-25 22:39:10

+0

謝謝,但該教程是關於使用XMLConfiguration的自定義配置文件。我看不出這對我有什麼幫助。 – 2013-03-25 22:41:56

3

我自己遇到了類似的問題。例如,在應用「Poco :: XML :: NodeFilter :: SHOW_ALL」過濾器的情況下,當通過XML文檔進行迭代時,將包括所有節點類型(Element,Text,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 
-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; 
} 

希望有所幫助。

0

遊戲後期,但可能仍然有用。我正在研究Poco XML以提取以xml傳遞的天氣數據。我發現PDF-slide @Jently是一個很好的介紹。這提供了hpp文件。這個example涵蓋了實現。我省略了LexicalHandler。

我查看字符串listOfReactions,發現時,我將屬性名和值添加到startElement()中的字符串中。在字符()中,我將節點中的文本添加到字符串中,並將其添加到可以遍歷的矢量中。

輸出:

ID = J1,可逆=假,假動作
ID = J2,可逆=真,真招

我改變你的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) { 
} 
相關問題