Boost Property_Tree итераторы, как с ними справиться?
Прошу прощения, раньше я задавал вопрос по той же теме, но моя проблема касается другого аспекта описанного там (Как повторить повышение...).
Взгляните на следующий код:
#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;
}
Ну, как мне сказали, в упомянутом мне вопросе, есть возможность использовать итераторы на property_tree
в Boost, но я не знаю, какой он тип, и какие методы или свойства я могу использовать.
Ну, я полагаю, что он должен быть другим ptree
или чем-то другим, который будет отображаться в другой иерархии xml, чтобы снова просматривать (если хотите), но документация об этом очень плоха. Я не знаю, почему, но в boost docs я не могу найти ничего хорошего, просто что-то о макросе для просмотра узлов, но этот подход - это тот, который мне бы очень хотелось избежать.
Итак, перейдем к моему вопросу: после получения итератора на ptree
, как я могу получить доступ к node имени, значениям, параметрам (a node в XML файле)?
Thankyou
Ответы
Ответ 1
Я согласен с Andry и считаю, что документация property_tree минимально минимальна. Мне понадобилось ptree для загрузки идентичных объектов с разными настройками, и мне не удалось выяснить, что итератор выполняет итерации, какой тип он вернет и останется ли он на уровне объектов, или пройти через каждый node BFS-подобный. Наконец, мне удалось заставить мой код работать в случае, аналогичном следующему:
файл настроек:
<object1>
<enable>true</enable>
<label>hello</label>
</object1>
<object2>
<enable>false</enable>
<label>goodbye</label>
</object2>
Сначала я добавил конструктор для моего объекта, который может инициализироваться на 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");
}
Наконец, следующий код загружает оба объекта и помещает их в карту:
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);
}
}
Итак, чтобы ответить на мои вопросы:
- Итератор выполняет итерацию по файлу настроек без перехода на более низкие уровни. Запустив этот код, вы обнаружите, что цикл повторяется дважды - один раз для каждого объекта в файле XML.
- Итератор возвращает объект value_type, который напоминает пару, и имеет аксессоры
first
и second
. v.first
является std::string, содержащим родительский node (в моем случае "object1", "object2" ), а v.second
- это boost::property_tree::ptree
, который может использоваться для анализа полей объекта.
Ответ 2
напечатать полное дерево:
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);
}
}
Ответ 3
Вы должны иметь предварительные знания в файле свойств ввода.
Дерево свойств Boost не является общим парсером документа. Он будет анализировать и предоставлять доступ к данным, но должен найти его вручную.
Я не знаю, есть ли метод навигации по всему документу, но если вам нужны только свойства собственного файла, вы можете сделать это с помощью очень простого кода.
Из повысить документацию:
1) Бросив версия (get):
ptree pt;
/* ... */
float v = pt.get<float>("a.path.to.float.value");
2) Версия по умолчанию (get):
ptree pt;
/* ... */
float v = pt.get("a.path.to.float.value", -1.f);
3) Дополнительная версия (get_optional):
ptree pt;
/* ... */
boost::optional<float> v = pt.get_optional<float>("a.path.to.float.value");