提升XML - 获取下一个节点

时间:2014-11-22 14:38:14

标签: c++ xml boost

以下代码尝试从xml文件中获取数据并将其添加到自定义SensorConfiguration类,然后将其添加到这些SensorConfigurations的映射中

我的问题是它总是在第二个foreach循环中采用第一个传感器配置。 我知道为什么,但我不知道正确的语法,而且我不确定如何谷歌这一点。

这是XML:

<?xml version="1.0" encoding="utf-8"?>
<root>
<sensorconfigurations>
    <configuration>
        <name>SensorConfiguration1</name>
        <sensorid>1</sensorid>
        <signalindex>1</signalindex>
        <mappingscheme>mappingscheme1</mappingscheme>
        <soundpack>test1.wav</soundpack>
    </configuration>
    <configuration>
        <name>SensorConfiguration2</name>
        <sensorid>2</sensorid>
        <signalindex>2</signalindex>
        <mappingscheme>mappingscheme1</mappingscheme>
        <soundpack>test2.wav</soundpack>
    </configuration>
    <configuration>
        <name>SensorConfiguration3</name>
        <sensorid>3</sensorid>
        <signalindex>3</signalindex>
        <mappingscheme>mappingscheme2</mappingscheme>
        <soundpack>test3.wav</soundpack>
    </configuration>
</sensorconfigurations>
</root>

这里是整个函数构造函数方法:

SensorConfigurationBank::SensorConfigurationBank()
{   
string m_level;
using boost::property_tree::ptree;
ptree pt;
read_xml("SensorConfigurationBank.xml", pt);
BOOST_FOREACH(ptree::value_type &v,
    pt.get_child("root.sensorconfigurations"))
{
    SensorConfiguration newSensorConf;
    BOOST_FOREACH(ptree::value_type &w,
        pt.get_child("root.sensorconfigurations.configuration"))
    {
        if(w.first == "name")
        {
            newSensorConf.setName(w.second.data());
        }
        if(w.first == "sensorid")
        {
            string stringToInt = w.second.data();
            istringstream iss(stringToInt);
            int value;
            iss >> value;
            newSensorConf.setSensorID(value);
        }
        if(w.first == "signalindex")
        {
            string stringToInt = w.second.data();
            istringstream iss(stringToInt);
            int value;
            iss >> value;
            newSensorConf.setSignalIndex(value);
        }
        if(w.first == "mappingscheme")
        {
            newSensorConf.setMappingScheme(getMappingScheme(w.second.data()));
        }
        if(w.first == "soundpack")
        {
            newSensorConf.setSoundPack(w.second.data());
        }
    }
    sensorConfigurations_.insert(make_pair(newSensorConf.getName(), newSensorConf));
}
//save();
}

我知道这有点难以理解,但这里有重要的部分:

BOOST_FOREACH(ptree::value_type &w,
        pt.get_child("root.sensorconfigurations.configuration"))

我希望它能够找到第一个循环正在查看的子节点,而不是获取特定的子节点配置,因此它会查看配置#2,而不是将配置#1连接到无限次。

它基本上只是我粘贴在上面的最后一行代码需要以某种方式进行更改,然后我认为它会起作用!提前谢谢。

1 个答案:

答案 0 :(得分:1)

  • get_child获取具有指定节点名称的单个树。您似乎希望它返回所有匹配的节点。事实并非如此。

  • Foreach迭代该值,您根本没有使用v。变化:

        if (v.first == "configuration")
        {
             // use v.second, which is the subtree
    
  • 节点路径是相对的,所以不要一直以“root.sensorconfigurations”开头:

    BOOST_FOREACH(ptree::value_type & v, pt.get_child("root.sensorconfigurations")) {
    
        if (v.first == "configuration")
        {
            SensorConfiguration newSensorConf;
    
            BOOST_FOREACH(ptree::value_type & w, v.second) {
                if (w.first == "name") {
                    newSensorConf.setName(w.second.data());
                }
    

查看 Live On Coliru

#include <iostream>
#include <string>
#include <map>

#include <boost/foreach.hpp>
#include <boost/strong_typedef.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/lexical_cast.hpp>

struct SensorConfiguration {
    void setName(std::string const& v) { _name = v; }
    std::string getName() const { return _name; }
    void setMappingScheme(std::string) {}
    void setSoundPack(std::string) {}
    void setSensorID(int) {}
    void setSignalIndex(int) {}

    std::string _name;
};

struct MyDemo {

    MyDemo() {
        std::string m_level;
        using boost::property_tree::ptree;
        ptree pt;
        read_xml("SensorConfigurationBank.xml", pt);
        BOOST_FOREACH(ptree::value_type & v, pt.get_child("root.sensorconfigurations")) {

            if (v.first == "configuration")
            {
                SensorConfiguration newSensorConf;

                BOOST_FOREACH(ptree::value_type & w, v.second) {
                    if (w.first == "name") {
                        newSensorConf.setName(w.second.data());
                    }
                    if (w.first == "sensorid") {
                        std::string stringToInt = w.second.data();
                        std::istringstream iss(stringToInt);
                        int value;
                        iss >> value;
                        newSensorConf.setSensorID(value);
                    }
                    if (w.first == "signalindex") {
                        std::string stringToInt = w.second.data();
                        std::istringstream iss(stringToInt);
                        int value;
                        iss >> value;
                        newSensorConf.setSignalIndex(value);
                    }
                    if (w.first == "mappingscheme") {
                        newSensorConf.setMappingScheme(getMappingScheme(w.second.data()));
                    }
                    if (w.first == "soundpack") {
                        newSensorConf.setSoundPack(w.second.data());
                    }
                }
                sensorConfigurations_.insert(make_pair(newSensorConf.getName(), newSensorConf));
            }
        }
        // save();

    }

    std::map<std::string, SensorConfiguration> sensorConfigurations_;

    template <typename T>
        std::string getMappingScheme(T const& v) {
            std::cout << __PRETTY_FUNCTION__ << "\n";
            return boost::lexical_cast<std::string>(v);
        }

};

int main() { 
    MyDemo demo;

    for(auto & e : demo.sensorConfigurations_)
        std::cout << e.first << "\n";
}