C++ Boost Property_Tree 迭代器,如何处理它们?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4597048/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Boost Property_Tree iterators, how to handle them?
提问by Andry
I am sorry, I asked a question about the same topic before, but my problem concerns another aspect of the one described there (How to iterate a boost...).
对不起,我之前问过一个关于同一主题的问题,但我的问题涉及那里描述的另一个方面(如何迭代提升......)。
Take a look at the following code:
看看下面的代码:
#include <iostream>
#include <string>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
#include <boost/algorithm/string/trim.hpp>
int main(int argc, char** argv) {
using boost::property_tree::ptree;
ptree pt;
read_xml("try.xml", pt);
ptree::const_iterator end = pt.end();
for (ptree::const_iterator it = pt.begin(); it != end; it++)
std::cout << "Here " << it->? << std::endl;
}
Well, as I got told told in the question I mentioned, there is the possibility to use iterators on property_tree
in Boost, but I do not know what type it is, and what methods or properties I can use.
好吧,正如我在我提到的问题中被告知的那样,可以property_tree
在 Boost 中使用迭代器,但我不知道它是什么类型,以及我可以使用哪些方法或属性。
Well, I assume that it must be another ptree
or something representing another xml hierarchy to be browsed again (if I want) but documentation about this is very bad. I do not know why, but in boost docs I cannot find nothing good, just something about a macro to browse nodes, but this approach is one I would really like to avoid.
好吧,我假设它必须是另一个ptree
或代表另一个 xml 层次结构的东西才能再次浏览(如果我愿意),但是关于此的文档非常糟糕。我不知道为什么,但在 boost 文档中我找不到任何好的东西,只是关于浏览节点的宏的一些东西,但这种方法是我真正想避免的方法。
So getting to my question here: Once getting the iterator on a ptree
, how can I access node name, value, parameters (a node in a xml file)?
Thankyou
所以在这里提出我的问题:一旦在 a 上获取迭代器ptree
,我如何访问节点名称、值、参数(xml 文件中的节点)?谢谢
回答by Andriy Tylychko
print complete tree:
打印完整的树:
void print(boost::property_tree::ptree const& pt)
{
using boost::property_tree::ptree;
ptree::const_iterator end = pt.end();
for (ptree::const_iterator it = pt.begin(); it != end; ++it) {
std::cout << it->first << ": " << it->second.get_value<std::string>() << std::endl;
print(it->second);
}
}
回答by bavaza
I agree with Andry, and find the documentation of property_tree to be extremely minimal at the least. I needed ptree for loading identical objects with different settings, and had trouble figuring out what the iterator iterates over, what type it returns, and whether or not it will remain on the objects level, or go through every node BFS-like. Finally, I managed to get my code working for a case similar to the following:
我同意 Andry 的观点,并且发现 property_tree 的文档至少非常少。我需要 ptree 来加载具有不同设置的相同对象,并且无法弄清楚迭代器迭代的内容,返回的类型,以及它是否会保留在对象级别,或者像 BFS 一样遍历每个节点。最后,我设法让我的代码在类似于以下的情况下工作:
settings file:
设置文件:
<object1>
<enable>true</enable>
<label>hello</label>
</object1>
<object2>
<enable>false</enable>
<label>goodbye</label>
</object2>
First, I added a constructor for my object, which can initialize on a ptree. Note that I'm using the get with default option, to prevent exception on failed get()'s:
首先,我为我的对象添加了一个构造函数,它可以在 ptree 上初始化。请注意,我使用的是带有默认选项的 get,以防止 get() 失败时出现异常:
object::object(const boost::property_tree::ptree &pt_)
{
enable = pt_.get<bool>("enable", true); // usage is: get<type>(path, default)
label = pt_.get<std::string>("label", "empty");
}
Finally the following code loads both objects, and places them in a map:
最后,以下代码加载两个对象,并将它们放置在地图中:
std::map<std::string, my_object> objects_map;
// parse settings file and add loggers
if(filesystem::exists(logger_settings_file))
{
boost::property_tree::ptree pt;
read_xml(logger_settings_file, pt);
BOOST_FOREACH(boost::property_tree::ptree::value_type &v, pt)
{
objects_map[v.first] = my_object(v.second);
}
}
So, to answer my own questions:
所以,回答我自己的问题:
- The iterator iterates over the settings file without descending into lower levels. Running the above code you will find that the loop iterates twice - one time for each object in the XML file.
- The iterator returns a value_type object which resembles a pair, and has the
first
andsecond
accessors.v.first
is an std::string holding the parent node (in my case "object1", "object2"), andv.second
is aboost::property_tree::ptree
, which can be used to parse the fields of the object.
- 迭代器在不下降到较低级别的情况下迭代设置文件。运行上面的代码,你会发现循环迭代了两次——对于 XML 文件中的每个对象一次。
- 迭代器返回一个 value_type 对象,它类似于一对,并具有
first
和second
访问器。v.first
是一个 std::string 保存父节点(在我的例子中为“object1”,“object2”),并且v.second
是一个boost::property_tree::ptree
,可用于解析对象的字段。
回答by 9dan
You should have the prior knowledge on the input property file.
您应该对输入属性文件有先验知识。
Boost property tree is not a general document parser. It will do parsing and give access to the data, but must locate it manually.
Boost 属性树不是通用的文档解析器。它将进行解析并提供对数据的访问权限,但必须手动定位。
I don't know there are method to navigate whole document, but if you only need the properties of your own file you can do it with very simple code.
我不知道有什么方法可以导航整个文档,但是如果您只需要自己文件的属性,则可以使用非常简单的代码来完成。
From the boost documentation:
从提升文档:
1) The throwing version (get):
1)投掷版(get):
ptree pt;
/* ... */
float v = pt.get<float>("a.path.to.float.value");
2) The default-value version (get):
2)默认值版本(get):
ptree pt;
/* ... */
float v = pt.get("a.path.to.float.value", -1.f);
3) The optional version (get_optional):
3)可选版本(get_optional):
ptree pt;
/* ... */
boost::optional<float> v = pt.get_optional<float>("a.path.to.float.value");