Boost Property Tree and its XML parser
- Tutorial

What is this article about
The article talks about the Property Tree Library, namely:
- What is a Property Tree;
- Examples of using the Property Tree;
- How to convert Property Tree to XML code and vice versa.
Property tree
Starting in version 1.41.1, the Property Tree library has appeared in Boost. This library provides a new data type, the boost :: propetry_tree :: ptree tree structure.
ptree is an ordinary tree structure, each element of which, in addition to data, can contain an ordered list of child elements, each of which has its own name.
The structure looks like this:
structptree
{
data_type data; // Данные элементаlist<pair<key_type, ptree>> children; // упорядочненный список дочерних элементов
};
Basically, a plain string is used as key_type.
Property Tree Examples
The ptree structure is very convenient for reading, writing, saving and loading tree data.
Adding items to this tree is as easy as shelling pears:
boost::property_tree::ptree heroTree;
heroTree.put("Name", "John");
heroTree.put("Exp", 150);
heroTree.put("Inventory.Weapon", "Blue Sword");
heroTree.put("Inventory.Money", 3000);
Since ptree contains a linked list, you can add several items that have the same key:
heroTree.put("Inventory.Item", "Stone");
heroTree.put("Inventory.Item", "Golden helmet");
heroTree.put("Inventory.Item", "Thomb key");
Would you like to get a sub-tree? Nothing too complicated:
boost::property_tree::ptree inventoryTree = heroTree.get_child("Inventory");
inventoryTree.put("Item", "Shield of Honor");
Retrieving items is also as simple as possible:
intexp = pt.get<int>("Exp");
std::string weapon = pt.get<std::string>("Inventory.Weapon");
If the item cannot be found, an exception is thrown. If you do not want this, simply set the second parameter to the value that you want to see by default:
intexp = pt.get<int>("Exp", 0);
If several elements are expected, then you have to sort them out:
BOOST_FOREACH(auto &v, inventoryTree)
{
if (v.first == "Item")
{
std::cout << "Hero has item: " << v.second.get<std::string>("") << std::endl;
}
}
XML parser
The great thing about the Property Tree Library is that the library contains built-in XML and JSON parsers. Parsers are not perfect, but they work right out of the box - you don’t need to drag any additional libraries and dependencies.
I did not work with the JSON parser, but I use the XML parser to the fullest. I’ll write about him in more detail.
For reading xml and writing xml, the read_xml and write_xml methods are used, respectively. The use is very simple:
//XML-код для парсингаstd::string xmlCode = "<ButtonList>\
<Button>B1</Button>\
<Button>B2</Button>\
</ButtonList>";
//Создаем потокstd::stringstreamstream(xmlCode);
try
{
boost::property_tree::ptree propertyTree;
//Читаем XML
boost::property_tree::read_xml(stream, propertyTree);
//Читаем значения:
BOOST_FOREACH(auto &v, propertyTree)
{
std::cout << "Button is " << v.second.get<std::string>("") << std::endl;
}
//Добавляем пару значений
propertyTree.put("ButtonList.Button", "B3");
propertyTree.put("ButtonList.Button", "B4");
std::stringstream output_stream;
//Записываем в другой поток
boost::property_tree::write_xml(output_stream, propertyTree);
//Получаем XML из потокаstd::string outputXmlCode = output_stream;
}
catch(boost::property_tree::xml_parser_error)
{
std::cout<<"XML parser error!"<<std::endl;
throw;
}
If you need to read the node attribute, you can do this through the pseudo subtree "<xmlattr>":
//XML-код для парсингаstd::string xmlCode = "<Data name="Position" x="5" y="5"/>";
//... парсим XML//Получаем значенияstd::string name = propertyTree.get<std::string>("Data.<xmlattr>.name");
int x = propertyTree.get<std::string>("Data.<xmlattr>.x");
int y = propertyTree.get<std::string>("Data.<xmlattr>.y");
With the pseudo-subtree "<xmlattr>", a small rake is connected that can be accidentally stepped on. Suppose, as in the above example, you have a ButtonList element in which there are 4 Button elements - these are the elements that characterize the buttons.
If the ButtonList element does not have attributes, then in the tree created on the basis of XML there will be 4 subtrees with buttons, as it should be. If ButtonList has any attributes, then - a surprise! - another subtree is added to the 4 subtrees with buttons, with the key "<xmlattr>", which obviously has no relation to the buttons.
If we go through all the subtrees directly, then together with the buttons we will try to process "<xmlattr>", and this will cause an error.
Therefore, when enumerating child trees, you will have to do an additional check, which will exclude <xmlattr> from the enumeration list. For example, like this:
BOOST_FOREACH(auto &v, propertyTree)
{
if (v.first == "Button") //Вводим дополнительную проверку
{
std::cout << "Button is " << v.second.get<std::string>("") << std::endl;
}
}
Other
In addition to the XML parser, the Property Tree Library also contains JSON, INI, and INFO parsers. I have not yet dealt with them, but I suppose that everything is there about the same.
List of used literature:
www.boost.org/doc/libs/1_52_0/doc/html/property_tree.html