Повысить итераторы Property_Tree, как с ними справиться? - PullRequest
14 голосов
/ 04 января 2011

Извините, я задавал вопрос на ту же тему раньше, но моя проблема касается другого аспекта, описанного там ( Как повторить повышение ... ).

Взгляните на следующий код:

#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 я не могу найти ничего хорошего, просто кое-что о макросе для просмотра узлов, но я бы очень хотел избежать этого подхода.

Итак, перейдем к моему вопросу здесь:Как получить итератор для ptree, как я могу получить доступ к имени узла, значению, параметрам (узлу в XML-файле)?Thankyou

Ответы [ 3 ]

19 голосов
/ 04 января 2011

печать полного дерева:

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);
    }
}
18 голосов
/ 23 января 2011

Я согласен с Андри и нахожу документацию property_tree крайне минимальной.Мне понадобилось ptree для загрузки идентичных объектов с разными настройками, и я не мог понять, что повторяет итератор, какой тип он возвращает, и останется ли он на уровне объектов, или будет проходить через каждый узел, похожий на BFS.Наконец, мне удалось заставить мой код работать для случая, подобного следующему:

файл настроек:

<object1>
    <enable>true</enable>
    <label>hello</label>
</object1>
<object2>
    <enable>false</enable>
    <label>goodbye</label>
</object2>

Сначала я добавил конструктор для моего объекта, который можно инициализировать вPtree.Обратите внимание, что я использую опцию get with default, чтобы предотвратить исключение при сбое 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, содержащая родительский узел (в моем случае «object1», «object2»), а v.second - это boost::property_tree::ptree, который можно использовать для анализа полей объекта.
0 голосов
/ 04 января 2011

Вы должны иметь предварительные знания о файле входных свойств.

Дерево свойств 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");
...