1

I need to make a simple input-output of the XML file. I'm using the boost::ptree.

struct structure
{
    std::string str;
    int ival;
    std::list<bool> bval;

    void save(const std::string& filename) {
        ptree pt;
        pt.put("main.str", str);
        pt.put("main.ival", ival);

        for (const auto& x : bval)
            pt.put("main.bval.b", x); 

        write_xml(filename, pt);
    }

    void load(const std::string& filename) {
        ptree pt;

        read_xml(filename, pt);

        str = pt.get("main.str", str);
        ival = pt.get("main.ival", ival);

        for(auto& v : pt.get_child("main.bval"))
             bval.insert(v.second.data());
    }
};

int main()
{
    structure b, s;
    s.str = "abc";
    s.ival = 14;
    s.bval = { 1, 0, 0, 1, 0, 1, 0, 0, 0, 1 };

    try
    {
        s.save("zxx.xml");

        b.load("zxx.xml");
    }
    catch (std::exception& exc)
    {
        std::cout << exc.what() << std::endl;
    }
    return 0;
}

The input doesn't work correctly because only one element of the "bval" write in the file. Also, I don't know how to make the output of this container (bval). Please help!

johnsnow
  • 13
  • 3

1 Answers1

1

You should simply replace put with add. "Put" assumes that the key should not be recreated.

With this fix, you can do a roundtrip:

    s.save("zxx.xml");
    b.load("zxx.xml");
    b.save("zxx2.xml");

Now, you can test that zxx.xml is equal to zxx2.xml.

See it Live On Coliru prints:

g++ -std=c++11 -Os -Wall -pedantic main.cpp && ./a.out && md5sum *.xml
8a91a9b67d3ac4518e59d23c90edabb0  zxx.xml
8a91a9b67d3ac4518e59d23c90edabb0  zxx2.xml

Listing

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <list>
#include <iostream>

using boost::property_tree::ptree;

struct structure
{
    std::string str;
    int ival;
    std::list<bool> bval;

    void save(const std::string& filename) {
        ptree pt;
        pt.put("main.str", str);
        pt.put("main.ival", ival);

        for (const auto& x : bval)
            pt.add("main.bval.b", x); 

        write_xml(filename, pt);
    }

    void load(const std::string& filename) {
        ptree pt;

        read_xml(filename, pt);

        str = pt.get("main.str", str);
        ival = pt.get("main.ival", ival);

        for(auto& v : pt.get_child("main.bval"))
        {
             bval.push_back(v.second.get<bool>(""));
        }
    }
};

int main()
{
    structure b, s;
    s.str = "abc";
    s.ival = 14;
    s.bval = { 1, 0, 0, 1, 0, 1, 0, 0, 0, 1 };

    try
    {
        s.save("zxx.xml");

        b.load("zxx.xml");

        b.save("zxx2.xml");
    }
    catch (std::exception& exc)
    {
        std::cout << exc.what() << std::endl;
    }
    return 0;
}
sehe
  • 374,641
  • 47
  • 450
  • 633
  • Thanks a lot! But what's it? **bval.insert(bval.end(), "true" == v.second.data());** Also another question: what does the function **data()**? – johnsnow Sep 14 '14 at 16:38
  • Oh, that part was irrelevant to your question and I just fixed it so it compiled. The answer to your question is in the line with `pt.add("main.bval.b", x);` (also the first sentence of my answer) – sehe Sep 14 '14 at 17:00
  • Yes, I understand. I just want to understand what is that line and what does that function. – johnsnow Sep 14 '14 at 17:07
  • That is why the date() returns the string? Does the returned object require additional cast? `bval.insert(bval.end(), boost::lexical_cast(v.second.data()));` It works. – johnsnow Sep 14 '14 at 17:15
  • Then why the function get() works without any casts? – johnsnow Sep 14 '14 at 17:22
  • `get` deduces the value conversion from the argument type... The insert... inserts the value at the end. I did a quick and dirty conversion using `"true" = data()` but yeah, `boost::lexical_cast` would be better already. Alternatively, **[use `get("")`](http://coliru.stacked-crooked.com/a/26adaacc3e28462f)** (answer also updated). – sehe Sep 14 '14 at 18:26