writing more complex than trivial xml with boost property tree

Oleg Vazhnev picture Oleg Vazhnev · Sep 18, 2013 · Viewed 10.5k times · Source

UPD I've found answer to "formatting" issue here, so I remove this part of the question, please read updated question:

I need to write xml to file system on c++. I've learned this titorial. In the tutorial pretty simple xml is used. My xml is more complicated and I don't know how to modify the code to produce it. That's what I've code:

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

//<Root>
//  <Set Name="1">
//      <Field Name="Hello 1"/>
//      <Field Name="World 1"/>
//  </Set>
//  <Set Name="2">
//      <Field Name="Hello 2"/>
//      <Field Name="World 2"/>
//  </Set>
//</Root>

int main(int argc, char* argv[])
{
    using boost::property_tree::ptree;
    ptree pt;

    pt.put("Root.Set.Field", "Hello");
    pt.put("Root.Set.Field", "World");

    boost::property_tree::xml_writer_settings<char> settings('\t', 1);
    write_xml("testXml.xml", pt, std::locale(), settings);
    return 0;
}

Output is:

<?xml version="1.0" encoding="utf-8"?>
<Root>
<Set>
    <Field>World</Field>
</Set>
</Root>

How can I modify my program to produce desired xml, in particular:

  • How to add multiple nods with the same name? Adding true like that pt.put("Root.Set.Field", "Hello", true); is compile time error
  • How to set xml attributes? (Name="Hello 1") According to doc It seems I should add them to "subkeys", but how?

upd i've tried that: pt.put("Root.Set.Field.xmlattr.Name", "Hello 1"); expecting to see that <Field Name="Hello 1"/> but still doesn't work. Waiting for someone who can share correct syntax.

upd2 bingo, this syntax works, i will continue try to print desired xml tomorrow. pt.put("Root.Set.Field.<xmlattr>.Name", "Hello 1");

Answer

Oleg Vazhnev picture Oleg Vazhnev · Sep 19, 2013

This answers the last question - how to use several nodes with the same name. Finally I wrote such program that solves the problem

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

//<Root>
//  <Set Name="1">
//      <Field Name="Hello 1"/>
//      <Field Name="World 1"/>
//  </Set>
//  <Set Name="2">
//      <Field Name="Hello 2"/>
//      <Field Name="World 2"/>
//  </Set>
//</Root>

int main(int argc, char* argv[])
{
    using boost::property_tree::ptree;
    ptree pt;

    boost::property_tree::ptree rootNode;
    boost::property_tree::ptree setNode1;
    boost::property_tree::ptree setNode2;
    boost::property_tree::ptree fieldNode1;
    boost::property_tree::ptree fieldNode2;
    boost::property_tree::ptree fieldNode3;
    boost::property_tree::ptree fieldNode4;

    fieldNode1.put("<xmlattr>.Name", "Hello 1");
    fieldNode2.put("<xmlattr>.Name", "World 1");
    fieldNode3.put("<xmlattr>.Name", "Hello 2");
    fieldNode4.put("<xmlattr>.Name", "World 2");

    setNode1.add_child("Field", fieldNode1);
    setNode1.add_child("Field", fieldNode2);
    setNode2.add_child("Field", fieldNode3);
    setNode2.add_child("Field", fieldNode4);

    setNode1.put("<xmlattr>.Name", "1");
    setNode2.put("<xmlattr>.Name", "2");

    rootNode.add_child("Set", setNode1);
    rootNode.add_child("Set", setNode2);
    pt.add_child("Root", rootNode);

    boost::property_tree::xml_writer_settings<char> settings('\t', 1);
    write_xml("testXml.xml", pt, std::locale(), settings);
    return 0;
}

Output:

<?xml version="1.0" encoding="utf-8"?>
<Root>
<Set Name="1">
    <Field Name="Hello 1"/>
    <Field Name="World 1"/>
</Set>
<Set Name="2">
    <Field Name="Hello 2"/>
    <Field Name="World 2"/>
</Set>
</Root>