Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding nodes with the same key to a property tree

Tags:

c++

xml

boost

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?

like image 904
Deekor Avatar asked Apr 21 '13 21:04

Deekor


1 Answers

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>
like image 90
Captain Obvlious Avatar answered Oct 16 '22 03:10

Captain Obvlious