XML解析
XML解析,通常可以有几种选择:
1: Tinyxml
2: boost::property_tree
根据tag, text, attribute的不同,可以将XML简单分成以下几种情况:
场景1
<calendar>
<Monday>
<weather>Rainy</weather>
</Monday>
<Tuesday>
<weather>Rainy</weather>
</Tuesday>
<Wednesday>
<weather>Sunny</weather>
</Wednesday>
<Thursday>
<weather>Cloudy</weather>
</Thursday>
</calendar>
在这种场景下,所有节点都没有attribute信息,而且在同一层次下的所有tag都是不相同的,比如Monday和Tuesday就是同一层次下不相同的两tag。
由于tag不相同,就保证了一条从root开始的tag路径只能索引到一条text信息。
这是最简单的应用场景,可以使用boost::property_tree的
std::string weather = tree.get<std::string>("calendar.Monday");
直接获取到text信息。
场景2
1: <calendar>
2: <days>
3: <day name="Monday">
4: <weather>Rainy</weather>
5: </day>
6: <day name="Tuesday">
7: <weather>Rainy</weather>
8: </day>
9: <day name="Wednesday">
10: <weather>Sunny</weather>
11: </day>
12: <day name="Thursday">
13: <weather>Cloudy</weather>
14: </day>
15: </days>
16: </calendar>
在这种场景下,同一层次下的各个子节点拥有相同的tag名称,用于区别各个节点的方法在于它们有一个相同名称的attribute,通过attribute的值来互相区分。
这种情况下,使用boost::property_tree就不那么容易操作了。
Why?
因为boost::property_tree是为了下面的场景http://www.boost.org/doc/libs/1_41_0/doc/html/property_tree.html
1: struct ptree
2: {
3: data_type data; // data associated with the node
4: list< pair<key_type, ptree> > children; // ordered list of named children
5: };
而设计的,这里的data相当于text,因此boost::property_tree没有显式地支持attribute,attribute也被作为一个child放在了children数组中。
因此要使用下面的代码
1: BOOST_FOREACH(boost::property_tree::ptree::value_type &day,
2: root.get_child("calendar.days"))
3: {
4: if (boost::iequals(day.first, "day"))
5: {
6: std::string attrVal = day.second.get<std::string>("<xmlattr>.name");
7: if (boost::iequals(attrVal, "Monday"))
8: {
9: std::string weather = day.second.get_child("weather").get_value<std::string>();
10: }
11: }
12: }
但是这种场景下,用TinyXml就方便多了,因为TinyXml可以支持attribute。