7

I am using Boost's property tree to read and write XML. Using a spreadsheet application I made I want to save the contents of the spreadsheet to xml. This is a school assignment so I am required to use the following format for the XML:

<?xml version="1.0" encoding="UTF-8"?>
<spreadsheet>
   <cell>
      <name>A2</name>
      <contents>adsf</contents>
   </cell>
   <cell>
      <name>D6</name>
      <contents>345</contents>
   </cell>
   <cell>
      <name>D2</name>
      <contents>=d6</contents>  
   </cell>
</spreadsheet>

For a simple test program I wrote:

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

pt.put("spreadsheet.cell.name", "a2");
pt.put("spreadsheet.cell.contents", "adsf");

write_xml("output.xml", pt);

boost::property_tree::ptree ptr;
read_xml("output.xml", ptr);

ptr.put("spreadsheet.cell.name", "d6");
ptr.put("spreadsheet.cell.contents", "345");
ptr.put("spreadsheet.cell.name", "d2");
ptr.put("spreadsheet.cell.contents", "=d6");

write_xml("output2.xml", ptr);

return 0;
}

Based on this question I see the put method replaces anything at that node, instead of adding a new one. Which is exactly the functionality I am seeing:

Output.xml

<?xml version="1.0" encoding="utf-8"?>
<spreadsheet>
  <cell>
    <name>a2</name>
    <contents>adsf</contents>
  </cell>
</spreadsheet>

Output2.xml

<?xml version="1.0" encoding="utf-8"?>
<spreadsheet>
  <cell>
    <name>d2</name>
    <contents>=d6</contents>
  </cell>
</spreadsheet>

Looking at the documentation I see this add_child method which will Add the node at the given path. Create any missing parents. If there already is a node at the path, add another one with the same key.

I can't quite figure out how to use that add_child method, could someone explain how to use it?

Is there a better way of going about this to achieve the file format I want?

Community
  • 1
  • 1
Deekor
  • 9,144
  • 16
  • 69
  • 121

1 Answers1

16

The add_child member function allows you to insert one property_tree into the DOM of another as a child node. If the key path you provide already exists a duplicate key will be added and the child will be inserted there instead. If we change your example a little bit we can examine the results.

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

int main()
{
    // Create the first tree with two elements, name and contents
    boost::property_tree::ptree ptr1;
    ptr1.put("name", "a2");
    ptr1.put("contents", "adsf");

    // Create the a second tree with two elements, name and contents
    boost::property_tree::ptree ptr2;
    ptr2.put("name", "d6");
    ptr2.put("contents", "345");

    // Add both trees to a third and place them in node "spreadsheet.cell"
    boost::property_tree::ptree ptr3;
    ptr3.add_child("spreadsheet.cell", ptr1);
    ptr3.add_child("spreadsheet.cell", ptr2);

    boost::property_tree::write_xml("output.xml", ptr3);

    return 0;
}

When you call add_child the first time, the node for key "spreadsheet.cell" does not exist and is created. It then adds the contents of the tree (name and contents) to the newly created node. When you call add_child the second time it sees that "spreadsheet.cell" already exists but unlike put it creates a sibling node also called "cell" and inserts it at the same location.

The final output:

<?xml version="1.0" encoding="utf-8"?>
<spreadsheet>
  <cell>
    <name>a2</name>
    <contents>adsf</contents>
  </cell>
  <cell>
    <name>d6</name>
    <contents>345</contents>
  </cell>
</spreadsheet>
MasonWinsauer
  • 673
  • 3
  • 14
  • 32
Captain Obvlious
  • 19,754
  • 5
  • 44
  • 74
  • Awesome explanation. If I were to want to update cell `d6` however, how would i navigate to that cell and change the contents in `ptr3`? – Deekor Apr 21 '13 at 22:59
  • 2
    @Deekor Iterate over the children of `spreadsheet` looking for all children of type `cell`. Anytime you encounter one get the contents of `name` and if you find a match delete it. You'll need to look at the docs for specifics – Captain Obvlious Apr 21 '13 at 23:03
  • nice explanation, not much documentation around add_child on net otherwise . – sb32134 Jan 21 '16 at 10:01
  • There is also `.add(name, value)`. – alfC Sep 23 '17 at 09:30