Using boost::property_tree

Some short examples of how to use the Boost property tree in order to read from and write to XML files.

Reading XML into a Boost property tree

Here’s how to read an example XML into the Boost property tree and traverse each of the the “item” sections within this XML, given that items may contain differing subsections:

For this XML example file “test1.xml” I use the following example XML taken from the Microsoft MSDN page:

<?xml version="1.0"?>
<purchaseOrder xmlns="http://tempuri.org/po.xsd" orderDate="1999-10-20">
    <shipTo country="US">
        <name>Alice Smith</name>
        <street>123 Maple Street</street>
        <city>Mill Valley</city>
        <state>CA</state>
        <zip>90952</zip>
    </shipTo>
    <billTo country="US">
        <name>Robert Smith</name>
        <street>8 Oak Avenue</street>
        <city>Old Town</city>
        <state>PA</state>
        <zip>95819</zip>
    </billTo>
    <comment>Hurry, my lawn is going wild!</comment>
    <items>
        <item partNum="872-AA">
            <productName>Lawnmower</productName>
            <quantity>1</quantity>
            <USPrice>148.95</USPrice>
            <comment>Confirm this is electric</comment>
        </item>
        <item partNum="926-AA">
            <productName>Baby Monitor</productName>
            <quantity>1</quantity>
            <USPrice>39.98</USPrice>
            <shipDate>1999-05-21</shipDate>
        </item>
    </items>
</purchaseOrder>

Supposing in the XML we wish to just iterate through and display all the “item” subsections within the “items” section only, excluding the “shipTo”, “billTo”, “comment” etc sections and their subsections. This is accomplished by obtaining and iterating over the “purchaseOrder.Items” child node(s), and then further obtaining and iterating over the “item” child nodes of these. We finally output the attribute label and its value:

C++ code to read and display the “item” node attributes of the boost property tree as follows:

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

const std::string XML_PATH1 = "./test1.xml";

int main()
{
    boost::property_tree::ptree pt1;
    boost::property_tree::read_xml( XML_PATH1, pt1  );

	 // Traverse property tree example
	BOOST_FOREACH( boost::property_tree::ptree::value_type const& node, pt1.get_child( "purchaseOrder.items" ) ) 
	{
		boost::property_tree::ptree subtree = node.second;  
		
        if( node.first == "item" ) 
		{
			BOOST_FOREACH( boost::property_tree::ptree::value_type const& v, subtree.get_child( "" ) ) 
			{
				std::string label = v.first;

				if ( label != "<xmlattr>" )
				{
					std::string value = subtree.get<std::string>( label );
					std::cout << label << ":  " << value << std::endl;
				}
			}
			std::cout << std::endl;
		}
    }

	return 0;
}

Which will find and display the 2 x “item” node attributes of the example XML file:

boost_property_tree_1

Once the XML is read into the Boost property tree, it is possible to obtain a specific value by way of the get command, the part number and zip code xml attributes for example:

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

#define XML_PATH1 "./test1.xml"

const std::string DEFAULT_PART_NO = "XYZ";
const std::string DEFAULT_ZIP = "90125";

int main()
{
    boost::property_tree::ptree pt1;
    boost::property_tree::read_xml( XML_PATH1, pt1  );

	std::string partNo = pt1.get<std::string>( "purchaseOrder.items.item.<xmlattr>.partNum",
	                                            DEFAULT_PART_NO);  

	std::cout << "Part number: " << partNo << std::endl;

	std::string zipCode = pt1.get<std::string>( "purchaseOrder.shipTo.zip",
	                                            DEFAULT_ZIP);  

	std::cout << "Zip Code: " << zipCode << std::endl;

	return 0;
}

Giving the output for part number and zip code:

boost_property_tree_2

Writing a Boost property tree to an XML file

It is possible to create a Boost property from a std::string, and then write the Boost property to an XML file:

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

const std::string XML = 
		"<file>"
		  "<people>"
			"<person>"
			  "<forename>Andrew</forename>"
			  "<surname>Jones</surname>"
			"</person>"
			"<person>"
			  "<forename>David</forename>"
			  "<surname>Matthews</surname>"
			"</person>"
			"<person>"
			  "<forename>Jason</forename>"
			  "<surname>Perkins</surname>"
			"</person>"
		  "</people>"
		"</file>";

int main()
{
    boost::property_tree::ptree pt;

	// Put the XML string into a stringstream
	std::stringstream is;
	is << XML;

	// Read the stringstream into a Boost property tree, pt
	boost::property_tree::read_xml( is, pt );

	// Then write the Boost property tree to an output XML file
	boost::property_tree::xml_writer_settings<char> w( ' ', 2 );  
	write_xml( "output.xml", pt, std::locale(), w );

	return 0;
}

Upon navigating to the same project folder after running this, observe that the XML file has been created:

boost_property_tree_3

Reading JSON files into a Boost property tree

Following on from an example posting at StackOverflow, an example of how to read in a JSON file into a Boost property tree.

Example JSON file "test1.json":

{
    "electron": {
        "pos": [0,0,0],
        "vel": [0,0,0]
    },

    "proton": {
        "pos": [1,0,0],
        "vel": [0,0.1,0]
    },

     "proton": {
        "pos": [-1,0,0],
        "vel": [0,-0.1,-0.1]
    }
}

C++ code recipe as follows:

#include <string>
#include <boost/property_tree/json_parser.hpp>
#include <boost/property_tree/ptree.hpp>
#include <boost/foreach.hpp>

const std::string JSON_PATH = "./test1.json";  

int main()  
{  
    boost::property_tree::ptree pt;
	boost::property_tree::read_json( JSON_PATH, pt );

	BOOST_FOREACH( boost::property_tree::ptree::value_type const& rowPair, pt.get_child( "" ) ) 
	{
		std::cout << rowPair.first << ": " << std::endl;

		BOOST_FOREACH( boost::property_tree::ptree::value_type const& itemPair, rowPair.second ) 
		{
			std::cout << "\t" << itemPair.first << " ";

			BOOST_FOREACH( boost::property_tree::ptree::value_type const& node, itemPair.second ) 
			{
				std::cout << node.second.get_value<std::string>() << " ";
			}

			std::cout << std::endl;

		}

		std::cout << std::endl;
    }
    
	std::cout << std::endl;
 
    return 0;  
}  

Giving the following output:

boost_property_tree_4