使用Boost解析XML属性
Parsing XML Attributes with Boost
我想和你分享一个问题,我正在尝试处理一些属性从XML元素在c++与Boost库(版本1.52.0)。给定以下代码:
#define ATTR_SET ".<xmlattr>"
#define XML_PATH1 "./pets.xml"
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
using namespace std;
using namespace boost;
using namespace boost::property_tree;
const ptree& empty_ptree(){
static ptree t;
return t;
}
int main() {
ptree tree;
read_xml(XML_PATH1, tree);
const ptree & formats = tree.get_child("pets", empty_ptree());
BOOST_FOREACH(const ptree::value_type & f, formats){
string at = f.first + ATTR_SET;
const ptree & attributes = formats.get_child(at, empty_ptree());
cout << "Extracting attributes from " << at << ":" << endl;
BOOST_FOREACH(const ptree::value_type &v, attributes){
cout << "First: " << v.first.data() << " Second: " << v.second.data() << endl;
}
}
}
假设我有以下XML结构:
<?xml version="1.0" encoding="utf-8"?>
<pets>
<cat name="Garfield" weight="4Kg">
<somestuff/>
</cat>
<dog name="Milu" weight="7Kg">
<somestuff/>
</dog>
<bird name="Tweety" weight="0.1Kg">
<somestuff/>
</bird>
</pets>
因此,我将得到的控制台输出将是下一个:
Extracting attributes from cat.<xmlattr>:
First: name Second: Garfield
First: weight Second: 4Kg
Extracting attributes from dog.<xmlattr>:
First: name Second: Milu
First: weight Second: 7Kg
Extracting attributes from bird.<xmlattr>:
First: name Second: Tweety
First: weight Second: 0.1Kg
但是,如果我决定对从根节点放置的每个元素使用一个公共结构(以便从它们的特定属性中识别它们),结果将完全改变。在这种情况下,这可能是XML文件:
<?xml version="1.0" encoding="utf-8"?>
<pets>
<pet type="cat" name="Garfield" weight="4Kg">
<somestuff/>
</pet>
<pet type="dog" name="Milu" weight="7Kg">
<somestuff/>
</pet>
<pet type="bird" name="Tweety" weight="0.1Kg">
<somestuff/>
</pet>
</pets>
输出如下:
Extracting attributes from pet.<xmlattr>:
First: type Second: cat
First: name Second: Garfield
First: weight Second: 4Kg
Extracting attributes from pet.<xmlattr>:
First: type Second: cat
First: name Second: Garfield
First: weight Second: 4Kg
Extracting attributes from pet.<xmlattr>:
First: type Second: cat
First: name Second: Garfield
First: weight Second: 4Kg
从根节点挂起的元素数量似乎被正确识别,因为已经打印了三组属性。尽管如此,它们都引用了第一个元素的属性…
我不是c++专家,对Boost也很陌生,所以这可能是我在哈希映射处理方面缺少的东西……如有任何建议,我将不胜感激。
程序的问题在这一行:
const ptree & attributes = formats.get_child(at, empty_ptree());
在这行中,您要求从pets
中获得子pet.<xmlattr>
,并且您独立于您正在遍历的f
执行此操作3次。在本文之后,我猜您需要使用的是:
const ptree & attributes = f.second.get_child("<xmlattr>", empty_ptree());
完整的代码,适用于你的xml文件,是:
#define ATTR_SET ".<xmlattr>"
#define XML_PATH1 "./pets.xml"
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
using namespace std;
using namespace boost;
using namespace boost::property_tree;
const ptree& empty_ptree(){
static ptree t;
return t;
}
int main() {
ptree tree;
read_xml(XML_PATH1, tree);
const ptree & formats = tree.get_child("pets", empty_ptree());
BOOST_FOREACH(const ptree::value_type & f, formats){
string at = f.first + ATTR_SET;
const ptree & attributes = f.second.get_child("<xmlattr>", empty_ptree());
cout << "Extracting attributes from " << at << ":" << endl;
BOOST_FOREACH(const ptree::value_type &v, attributes){
cout << "First: " << v.first.data() << " Second: " << v.second.data() << endl;
}
}
}
到目前为止还没有使用过这个特性,我怀疑boost::property_tree
XML解析器不是一个通用的XML解析器,而是期望一个特定的模式,在这个模式中,一个特定的属性恰好有一个特定的标记。
如果您想使用boost::property_tree
功能之外的XML,您可能更喜欢使用其他提供解析任何XML模式的XML解析器。看一下例如Xerces c++或Poco XML
待解析文件,pets.xml
<pets>
<pet type="cat" name="Garfield" weight="4Kg">
<something name="test" value="*"/>
<something name="demo" value="@"/>
</pet>
<pet type="dog" name="Milu" weight="7Kg">
<something name="test1" value="$"/>
</pet>
<birds type="parrot">
<bird name="african grey parrot"/>
<bird name="amazon parrot"/>
</birds>
</pets>
代码:// DemoPropertyTree.cpp : Defines the entry point for the console application.
//Prerequisite boost library
#include "stdafx.h"
#include <boost/property_tree/xml_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>
#include<iostream>
using namespace std;
using namespace boost;
using namespace boost::property_tree;
void processPet(ptree subtree)
{
BOOST_FOREACH(ptree::value_type petChild,subtree.get_child(""))
{
//processing attributes of element pet
if(petChild.first=="<xmlattr>")
{
BOOST_FOREACH(ptree::value_type petAttr,petChild.second.get_child(""))
{
cout<<petAttr.first<<"="<<petAttr.second.data()<<endl;
}
}
//processing child element of pet(something)
else if(petChild.first=="something")
{
BOOST_FOREACH(ptree::value_type somethingChild,petChild.second.get_child(""))
{
//processing attributes of element something
if(somethingChild.first=="<xmlattr>")
{
BOOST_FOREACH(ptree::value_type somethingAttr,somethingChild.second.get_child(""))
{
cout<<somethingAttr.first<<"="<<somethingAttr.second.data()<<endl;
}
}
}
}
}
}
void processBirds(ptree subtree)
{
BOOST_FOREACH(ptree::value_type birdsChild,subtree.get_child(""))
{
//processing attributes of element birds
if(birdsChild.first=="<xmlattr>")
{
BOOST_FOREACH(ptree::value_type birdsAttr,birdsChild.second.get_child(""))
{
cout<<birdsAttr.first<<"="<<birdsAttr.second.data()<<endl;
}
}
//processing child element of birds(bird)
else if(birdsChild.first=="bird")
{
BOOST_FOREACH(ptree::value_type birdChild,birdsChild.second.get_child(""))
{
//processing attributes of element bird
if(birdChild.first=="<xmlattr>")
{
BOOST_FOREACH(ptree::value_type birdAttr,birdChild.second.get_child(""))
{
cout<<birdAttr.first<<"="<<birdAttr.second.data()<<endl;
}
}
}
}
}
}
int _tmain(int argc, _TCHAR* argv[])
{
const std::string XML_PATH1 = "C:/Users/10871/Desktop/pets.xml";
ptree pt1;
boost::property_tree::read_xml( XML_PATH1, pt1 );
cout<<"********************************************"<<endl;
BOOST_FOREACH( ptree::value_type const& topNodeChild, pt1.get_child( "pets" ) )
{
ptree subtree = topNodeChild.second;
if( topNodeChild.first == "pet" )
{
processPet(subtree);
cout<<"********************************************"<<endl;
}
else if(topNodeChild.first=="birds")
{
processBirds(subtree);
cout<<"********************************************"<<endl;
}
}
getchar();
return 0;
}
输出如下所示:输出
相关文章:
- 使用 RapidXML 更新C++中的 XML 节点和属性值
- 按属性搜索和提取 XML 节点
- 尝试使用 RapidXML 将唯一的 XML 属性追加到节点
- 将具有 xml 属性的子树添加到提升属性树
- 如何使用 pugixml 正确访问 xml 属性?
- 使用提升属性树检查 xml 文件中是否存在元素
- 如何在Qt中解析未知的xml并获取其中的所有属性
- 如何将Boost属性树的子树序列化为XML
- 提升属性树:如何使用xml文件获取子树的子级
- 如何手动创建具有不同 XML 属性的提升 ptree
- 提升属性树(XML)删除空白行
- 使用QT的C 处理DOM处理后的XML属性顺序
- 使用 Boost 属性树解析 SVG (XML)
- 如何使用 boost 的 ptree 删除 XML 的属性?
- 使用 Qt 搜索具有特殊父级的 XML 属性
- 使用 XmlLite IXmlWriter (C++) 在 prolog 中创建不带编码属性的 XML
- 如何将复杂的指针数据作为属性放入qt-plugin-xml文件中
- 如何使用xerces向xml添加属性
- boost属性树xml编写器输出没有结束
- 获取 XML 文件的特定属性