catalogue
3.get() accesses the node through the path
4.get_child() gets a node object with multiple child nodes
7. Get comments and attribute values
10, property_tree
property_tree is a tree data structure that holds multiple attribute values. It can access the attributes of any node in a simple way similar to a path, and each node can traverse its child nodes in a style similar to STL. property_tree is especially suitable for application configuration data processing. It can parse text data in four formats: XML, JSON, INI and INFO. Using it can reduce the work of development configuration management.
property_ The core class of Tree Library is basic_ptree, which has two important internal type definitions: self_type and value_type . These two type definitions mean basic_ptree uses a composite pattern, which consists of multiple basic modules_ The ptree composite is like an STD:: List < key, basic_ptree> .
- self_type is basic_ptree template is its own type after instantiation, and it is also the type of child nodes.
- value_type is the data structure of a node. It is an std::pair, containing the attribute name (first) and the node itself (second).
Same as standard string class basic_ Like string, we usually don't use basic directly_ Ptree, but use predefined typedefs: ptree, wptree, iptree, wiptree. The prefix i in these names means to ignore case, and the prefix w means to support wide characters.
(1) Processing xml
1. Write xml and modify xml
property_tree can use write_xml() writes configuration information. It has two overloaded forms and can receive file names or input and output streams. Its operation is symmetrical. You can modify the node value of the attribute tree by using the template member function put(). If the child node does not exist, it is equivalent to adding a new node. If the child node exists, you can modify the node value locally. Put () usually does not need to specify template parameters because the type of attribute value can be derived automatically. If you want to add a new node with the same name to the attribute tree, you need to use the add() function.
#include <boost/property_tree/ptree.hpp> #include <boost/property_tree/xml_parser.hpp> void StudyWidgets::TestPropertyTree() { boost::property_tree::ptree write_pt; write_pt.put("info", "student info"); write_pt.put("info.name", "Lisa"); write_pt.put("info.age", 22); write_pt.put("info.subjects.subject", "Chinese"); write_pt.add("info.subjects.subject", "Math");//Add a new node to the attribute tree write_pt.add("info.subjects.subject", "English"); write_pt.put("info.teacher", "Tanasha"); write_pt.put("info.message", "She know PI is 3.141592653"); boost::property_tree::write_xml("./config1.xml", write_pt); }
<?xml version="1.0" encoding="utf-8"?> <info>student info <name>Lisa</name> <age>22</age> <subjects> <subject>Chinese</subject> <subject>Math</subject> <subject>English</subject> </subjects> <teacher>Tanasha</teacher> <message>She know PI is 3.141592653</message> </info>
2. Parsing xml
To parse the XML configuration file, we first use read_ The XML () function parses XML and initializes ptree. It has two overloaded forms and can receive file names or input and output streams.
void read_xml(const std::string &filename, Ptree &pt, int flags = 0, const std::locale &loc = std::locale());
The third parameter flags is a parameter that operates on text other than tags in xml. It can take values of 0, 1, 2 and 4, where 0 means no operation.
//xml_parser_flags.hpp static const int no_concat_text = 0x1; static const int no_comments = 0x2; static const int trim_whitespace = 0x4;
The fourth parameter is the locale object, which specifies the data format, such as date, line feed, code, etc. it can be defaulted. See Locale class usage of C + + standard library_ LEE's column - CSDN blog_ c++ locale
3.get() accesses the node through the path
After initializing ptree, we can use the template member function get() to access the nodes in the attribute tree through the path (the dot "." is used as the path separator by default), and use the template parameter to indicate the type of attribute obtained. Ptree's get() function supports the use of default values. You can specify the default value while specifying the path. If the property does not exist in the property tree, the default value is used. Since the default value already has type information, the return value type of get() can be derived automatically without adding template parameters.
By default, property_tree uses dot numbers to separate paths. Although it is not in line with the habits of the operating system and XML, it is natural to use it to represent hierarchical properties. However, sometimes dot numbers appear in the property name, and property_tree also allows us to use other separators, such as "/".
4.get_child() gets the node object with multiple child nodes
For a node with multiple child nodes, we need to use get_child() to obtain the child node object first, and then use begin() and end() to traverse the child nodes like using a standard container. The iterator points to the value_type of ptree. Its second member is the child node itself, and its value can be accessed directly by data() or get_value().
<?xml version="1.0" encoding="utf-8"?> <info>student info <!-- this is a note --> <name id="1">Lisa</name> <age>22</age> <subjects> <subject>Chinese</subject> <subject>Math</subject> <subject>English</subject> </subjects> <teacher language="English">Tanasha</teacher> <message> <![CDATA[10<100]]> </message> <NO.1>She knew the PI was 3.141592653</NO.1> </info>
boost::property_tree::ptree pt; boost::property_tree::read_xml("./config.xml", pt, 4); //get() accesses the nodes in the property tree through the path std::string name = pt.get<std::string>("info.name"); int age = pt.get<int>("info.age"); std::cout << "name:" << name << ",age:" << age << std::endl;//name:Lisa,age:22 //get() supports default values std::string sex = pt.get<std::string>("info.sex", "female"); std::cout << "sex:" << sex << std::endl; //sex: Female //get_child() gets a node object with multiple child nodes auto subjects = pt.get_child("info.subjects"); //Traversal: Method 1 for (auto& child : subjects) { std::cout << child.second.get_value<std::string>() << std::endl; } //Method 2 for (auto item = subjects.begin(); item != subjects.end(); item++) { std::cout << item->second.data() << std::endl; }
try { //NO.1:She know PI is 3.141592653 std::cout << "NO.1:" << pt1.get<std::string>(boost::property_tree::ptree::path_type("info/NO.1", '/')) << std::endl; } catch (std::exception e) { std::cout << e.what() << std::endl;// }
5.find() shallow search
We can also find the value of a node through the find() member function, but find() only supports shallow search and cannot achieve deep search.
//find() finds a node, which is shallow and does not support deep search auto item = pt.find("info"); std::cout << "info:" << item->second.data() << std::endl;//student info
6.get_optional()
The get() function has three forms. In addition to the previous basic form and default value form, there is also a get_option. It is also the use of the default value form, but it uses the optional library to wrap the return value. If get fails, the optional object is invalid.
auto teacher = pt.get_optional<std::string>("teacher");//It should be info.teacher if (teacher.is_initialized()) { std::cout << teacher.get() << std::endl; } else { std::cout << "teacher not exist" << std::endl;//teacher not exist }
7. Get comments and attribute values
Property_tree itself does not implement an XML parser, but uses the non Boost open source project rapidxml. Therefore, property_tree uses rapidxml to convert all XML nodes into nodes corresponding to the property tree. The tag name of the node is the property name, and the content of the node is the property value. The properties of the node are saved in the < xmlattr > subordinate node of the node, and the comments are saved in < xmlcomment > In, the text content of the node (such as CDATA) is saved in < xmitext >.
boost::property_tree::ptree pt1; boost::property_tree::read_xml("./config.xml", pt1); try { std::cout << "notes:" << pt1.get<std::string>("info.<xmlcomment>") << std::endl; std::cout << "id:" << pt1.get<std::string>("info.name.<xmlattr>.id") << std::endl; std::cout << "teacher language:" << pt1.get<std::string>("info.teacher.<xmlattr>.language") << std::endl; std::cout << "CDATA:" << pt1.get<std::string>("info.message") << std::endl; } catch (std::exception e) { std::cout << e.what() << std::endl; } //Note: this is a note //id:1 //teacher language:English //CDATA: // 10<100
(2) Deal with Jason
JSON (JavaScript object notation) is also a common data exchange format. Its structure is simple and compact. It is similar to XML, but there is not so much "red tape".
#include <boost/property_tree/json_parser.hpp>
(3) Processing ini
INI format is a very popular configuration data format under Windows operating system. It has been widely used, but it has some shortcomings over XML and JSON: it does not support multi-level hierarchy, only simple key / value form, and cannot express complex configuration. Therefore, configuration data in other formats may not be converted to INI format.
#include <boost/property_tree/ini_parser.hpp>
(4) Processing info
INFO format is a special format for property_tree. It is simpler than XML and its style is similar to JSON. However, INFO has many C + + features, such as # include statement, slash character escape, etc., which is especially suitable for C + + programmers.
#include <boost/property_tree/info_parser.hpp>