-->

与升压解析XML属性(Parsing XML Attributes with Boost)

2019-07-17 12:37发布

我想与大家分享,同时试图处理从C ++中的XML元素以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专家++和真正的新提升,所以这可能是我丢失的东西相对于哈希映射处理或使...任何意见将非常感激。

Answer 1:

与你的程序的问题位于这条线:

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

有了这条线,你是要求得到孩子pet.<xmlattr>pets和你单独取其做3次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;
        }
    }
}


Answer 2:

即使不使用此功能,到目前为止,我会怀疑boost::property_tree XML解析器是不常见的XML解析器,但预计有一定的模式,那就是你有一个特定的属性只有一个特定的标签。

你可能更喜欢使用提供任何解析XML模式,如果你想与超越XML的其它XML解析器boost::property_tree能力。 看看如Xerces的C ++或波科XML 。



Answer 3:

文件进行解析, 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;
}

输出如下所示: 输出



文章来源: Parsing XML Attributes with Boost