Добавление неназванных узлов в boost :: property_tree :: ptree - PullRequest
3 голосов
/ 11 ноября 2011

Мне нужно добавить неназванные узлы в boost :: property_tree :: ptree, как это делает JSON-анализатор для массивов.Однако, когда я хочу сделать это, я получаю такое утверждение во время выполнения:

  Assertion failed: !p.empty() && "Empty path not allowed for put_child.", file C:\Program Files\Boost\boost\include/boost/property_tree/detail/ptree_implementation.hpp, line 877

Я делаю это как

tree.add_child(name, child);

, где дерево и дочерний объект - это и ptree-s, и имя char *.

Как я могу сделать это так, как это делает парсер JSON для ptree-s?

Ответы [ 2 ]

12 голосов
/ 18 ноября 2011

Я не думаю, что Boost.Property_tree имеет веские основания для запрета пустых путей в add_child или put_child. Способ обнаружения корня реализован в их служебных программах внутреннего пути, требующих непустых путей.

Вы можете обойти это, не используя их утилиты маршрутизации при добавлении элементов массива.

using boost::property_tree::ptree;
ptree pt;
pt.put_child( "path.to.array", ptree() );
auto& array = pt.get_child( "path.to.array" );
array.push_back( std::make_pair( "", ptree("foo") ) );
array.push_back( std::make_pair( "", ptree("bar") ) );
boost::property_tree::json_parser::write_json( std::cout, pt, false );
// {"path":{"to":{"array":["foo","bar"]}}}
6 голосов
/ 14 июля 2013

Я приземлился здесь, пытаясь выяснить аналогичную проблему. Мне потребовалось время, чтобы решить ее, так что, надеюсь, этот пост поможет другим.

Для меня ключом к решению проблемы было помнить, что ptree - это коллекция boost :: property_tree :: ptree :: value_type. Таким образом, проблема сводится к тому, «как я могу добавить value_types из одного дерева в другое».

Ptree предоставляет несколько методов для вставки value_type:

iterator push_front(const value_type &);
iterator push_back(const value_type &);
iterator insert(iterator, const value_type &);

У Ptree нет определения типа const_reference, поэтому мы не можем использовать std :: copy с итератором back_inserter. Но мы можем использовать std :: for_each со связанной функцией.

#include <algorithm>
#include <functional>
#include <boost/property_tree/ptree.hpp>

using namespace std;
using namespace boost::property_tree;

...

ptree child;
child.put("Value1", 1);
child.put("Value2", 2);

ptree parent;
std::for_each(child.begin(),
              child.end(),
              std::bind(&ptree::push_back, &parent, placeholders::_1));

Теперь, если parent выведен как XML, он будет содержать:

<Value1>1</Value1>
<Value2>2</Value2>
...