pugixml получает один и тот же адрес для всех детей на одном уровне

мы видим, что адреса всех дочерних элементов на одном уровне одинаковы, это вредит нашей логике, поскольку мы хотим сохранить адреса узлов xml для последующей обработки. вот образец xml, который мы используем, и вывод.

XML:

<?xml version="1.0"?>
<network>
    <animation clip="idle" flags="loop" />
    <animation clip="run" flags="loop" />
    <animation clip="attack" />
    <?include transitions.xml?>
</network>

код:

#include <vector>
#include <iostream>
#include <string>
#include <map>
#include "pugixml.hpp"
#include "tinyformat.h"
#include <boost/filesystem.hpp>
#include <boost/algorithm/string.hpp>
#include <fstream>
#include <streambuf>
#include <tuple>
#include <algorithm>
#include <cctype>
#include <string>

int main( int ac, char **av )
{
    try {
        std::ifstream t("/home/rk/character.xml");
        std::string str((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
        std::string xml = str;
        pugi::xml_document *doc = new pugi::xml_document();
        auto result = doc->load_buffer_inplace ( const_cast <char*> ( xml.c_str() ), xml.size() );
        if ( result.status != pugi::xml_parse_status::status_ok ) {
            throw std::runtime_error ( std::string ( std::string( "Error parsing the xml: " )
                        +
                        std::string ( result.description() ) ));
        }
        std::cerr<<" children: " << std::endl;
        std::cerr<<" --------: " << std::endl;
        for ( pugi::xml_node_iterator it = doc->first_child().begin(); it != doc->first_child().end(); ++it ) {
            pugi::xml_node *element = &(*it);
            std::cerr << " type : " << element->name() 
                << " name : " << element->attribute("clip").as_string() 
                << " address : " << element 
                << std::endl;
        }
        std::cerr<<" --------: " << std::endl;
        return 0;
    } catch ( std::exception &ex ) {
        std::cerr<< " main exited with exception : " << ex.what() << std::endl;
        return -1;
    }
}

выход:

children: 
 --------: 
 type : animation name : idle address : 0x7ffde2386cc0
 type : animation name : run address : 0x7ffde2386cc0
 type : animation name : attack address : 0x7ffde2386cc0 <------ i was expecting different addresses

person Ravikumar Tulugu    schedule 18.09.2019    source источник


Ответы (1)


Я считаю, что это связано с тем, как реализован pugi::xml_node_iterator.

Если вы посмотрите на источник его operator++, вы увидите, что он изменяет какое-то состояние, а затем возвращает себя.

PUGI__FN const xml_node_iterator& xml_node_iterator::operator++()
{
    assert(_wrap._root);
    _wrap._root = _wrap._root->next_sibling;
    return *this;
}

Таким образом, в вашем цикле вы каждый раз получаете адрес одного и того же экземпляра, и затем ожидается ваш вывод. (Конечно, совершенно неожиданно по сравнению с более привычным std::iterator, который работает по-другому.)

person acraig5075    schedule 17.01.2020