如何使用 POCO 解析 xml 文件并将特定节点提取到 std::string?

Tot*_*son 2 c++ xml poco xml-parsing sbml

我想使用 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>
Run Code Online (Sandbox Code Playgroud)

我想提取 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();
}
Run Code Online (Sandbox Code Playgroud)

小智 5

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

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

XML 示例:

<?xml version="1.0"?>
<reaction id="J1" reversible="false">
Run Code Online (Sandbox Code Playgroud)

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();
}
...
Run Code Online (Sandbox Code Playgroud)

应该输出:

id : J1
reversible : false
Run Code Online (Sandbox Code Playgroud)

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

XML 示例:

<?xml version="1.0"?>
<listOfReactions>Some text</listOfReactions>
Run Code Online (Sandbox Code Playgroud)

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();
}
...
Run Code Online (Sandbox Code Playgroud)

应该输出:

Some text
Run Code Online (Sandbox Code Playgroud)