如何用Boost解析XML属性?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (132)

我正在尝试用Boost库处理C++中XML元素的一些属性(版本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

由于打印了三组属性,因此似乎正确地识别了根节点挂起的元素的数量。它们都提到了第一个元素的属性.

提问于
用户回答回答于

程序的问题位于以下一行:

const ptree & attributes = formats.get_child(at, empty_ptree());

用这句话你是想让孩子pet.<xmlattr>pets你做了三次,不管是哪一种f你在穿越。以下这篇文章我猜你需要用的是:

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;
        }
    }
}
用户回答回答于

它需要一个特定的模式,在这个模式中,一个特定属性恰好有一个特定的标记。如果您想使用XML之外的xml,则可能更愿意使用提供解析任何xml架构的其他xml解析器。boost::property_tree能力。看一看。Xerces C++POCO XML...

扫码关注云+社区