Search code examples
c++xmlboostboost-propertytree

Better XML formatting using Boost?


I'm using Boost Property Trees to export my class-instants as XML nodes. It works but it just puts everything in 1 line. I would like it to have indents, like:

<?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>

Is this possible somehow? Am I missing a parameter in the write_xml method?

Here's my code:

void SensorConfigurationBank::save()
{
using boost::property_tree::ptree;
ptree pt;
for(map<string, SensorConfiguration>:: iterator it = sensorConfigurations_.begin(); it != sensorConfigurations_.end(); ++it) 
{
    ptree myTree;
    myTree.put("name", it->second.getName());
    myTree.put("sensorid", it->second.getSensorID());
    myTree.put("signalindex", it->second.getsignalIndex());
    MappingScheme myScheme = it->second.getMScheme();
    myTree.put("mappingscheme", myScheme.getId());
    SoundPack mySound = it->second.getSound();
    myTree.put("soundpack", mySound.filepath_);

    pt.add_child("root.sensorconfigurations.configuration", myTree);
}
write_xml("SensorConfigurationBank2.xml", pt); 
}

Solution

  • These days, xml_writer_settings apparently takes a string type as template argument, so:

    boost::property_tree::xml_writer_settings<std::string> settings('\t', 1);
    write_xml(std::cout, pt, settings); 
    

    will do the trick. Full sample:

    Live On Coliru

    #include <boost/property_tree/ptree.hpp>
    #include <boost/property_tree/xml_parser.hpp>
    #include <map>
    #include <iostream>
    
    struct SoundPack {
        std::string filepath_ = "soundpack.wav";
    };
    struct MappingScheme {
        std::string getId()    const { return "Id";    }
    };
    struct SensorConfiguration {
        std::string   getName()        const { return "Name";        }
        std::string   getSensorID()    const { return "SensorID";    }
        std::string   getsignalIndex() const { return "signalIndex"; }
        SoundPack     getSound()       const { return {};            }
        MappingScheme getMScheme()     const { return {};            }
    };
    
    void save(std::map<std::string, SensorConfiguration> sensorConfigurations_)
    {
        using boost::property_tree::ptree;
        ptree pt;
        for(std::map<std::string, SensorConfiguration>:: iterator it = sensorConfigurations_.begin(); it != sensorConfigurations_.end(); ++it) 
        {
            ptree myTree;
    
            MappingScheme myScheme = it->second.getMScheme();
            SoundPack mySound = it->second.getSound();
    
            myTree.put("name",          it->second.getName());
            myTree.put("sensorid",      it->second.getSensorID());
            myTree.put("signalindex",   it->second.getsignalIndex());
            myTree.put("mappingscheme", myScheme.getId());
            myTree.put("soundpack",     mySound.filepath_);
    
            pt.add_child("root.sensorconfigurations.configuration", myTree);
        }
        boost::property_tree::xml_writer_settings<std::string> settings('\t', 1);
        write_xml(std::cout, pt, settings); 
    }
    
    int main() {
        save({
                { "first",  SensorConfiguration {} },
                { "second", SensorConfiguration {} },
                { "third",  SensorConfiguration {} },
                { "fourth", SensorConfiguration {} }
            });
    }
    

    Output:

    <?xml version="1.0" encoding="utf-8"?>
    <root>
        <sensorconfigurations>
            <configuration>
                <name>Name</name>
                <sensorid>SensorID</sensorid>
                <signalindex>signalIndex</signalindex>
                <mappingscheme>Id</mappingscheme>
                <soundpack>soundpack.wav</soundpack>
            </configuration>
            <configuration>
                <name>Name</name>
                <sensorid>SensorID</sensorid>
                <signalindex>signalIndex</signalindex>
                <mappingscheme>Id</mappingscheme>
                <soundpack>soundpack.wav</soundpack>
            </configuration>
            <configuration>
                <name>Name</name>
                <sensorid>SensorID</sensorid>
                <signalindex>signalIndex</signalindex>
                <mappingscheme>Id</mappingscheme>
                <soundpack>soundpack.wav</soundpack>
            </configuration>
            <configuration>
                <name>Name</name>
                <sensorid>SensorID</sensorid>
                <signalindex>signalIndex</signalindex>
                <mappingscheme>Id</mappingscheme>
                <soundpack>soundpack.wav</soundpack>
            </configuration>
        </sensorconfigurations>
    </root>