Рекурсивный проход по элементам XML

86
31 декабря 2020, 02:40

Я выбрал tinyxml2 для парсинга XML файлов, хочу узнать как рекурсивно обойти элементы XML.

text.XML

<data>
    <data>
        <username>johny1994</username>
        <realname>John Batcher</realname>
    </data>
    <data>
        <username>drdre222</username>
        <realname>Doctor Dree</realname>
    </data>
</data>

data - первый XML элемент, за ним следует дочерний data элемент, за дочерним data следуют дочерние username и realname. Дочерних data которые идут от корневого отца элемента data может быть N количество (в моем случае 2). Нужно найти все эти дочерние data элементы и пройтись по ним рекурсивно.

Код:

tinyxml2::XMLDocument doc;
tinyxml2::XMLError e = doc.LoadFile("text.xml");
if (e != tinyxml2::XML_SUCCESS) {
    std::cout << "Error load file" << std::endl;
}
auto root = doc.FirstChildElement("data");
if (root == nullptr)
{
    std::cout << "Child element not found\n";
}
// Тут должен быть какой-то код типа цикла для обработка data элементов
// что-то типа for (root; root < elementCount; ++root) {};
auto rootdata = root->FirstChildElement("data");
if (rootdata == nullptr)
{
    std::cout << "Child (data) element not found\n" << std::endl;
}
auto username = rootdata->FirstChildElement("username");
if (username == nullptr)
{
    std::cout << "username is null ptr" << std::endl;
}
std::cout << "Username:\t" << username->GetText() << std::endl;
auto realname = rootdata->FirstChildElement("username");
if (realname == nullptr)
{
    std::cout << "realname is null ptr" << std::endl;
}
std::cout << "Real name:\t" << realname->GetText() << std::endl;

Вывод должен быть примерно следующим:

Username: johny1994
Real name: John Batcher
Username: drdre222
Real name: Doctor Dre
Answer 1

Обычно рекурсию используют для продвижения вглубь дерева (от корня к листам). Не понимаю, зачем Вам рекурсивно пробегать по элементам одного уровня, по которым гораздо удобнее пройтись циклом:

auto root = doc.FirstChildElement("data");
if (root == nullptr)
{
    std::cout << "Child element not found\n";
}
// Тут должен быть какой-то код типа цикла для обработка data элементов
auto current_data = root->FirstChildElement("data");
auto last_data = root->LastChildElement("data");
do
{
    if (current_data == nullptr)
    {
        std::cout << "Child (data) element not found\n" << std::endl;
        break;
    }
    auto username = current_data->FirstChildElement("username");
    if (username == nullptr)
    {
        std::cout << "username is null ptr" << std::endl;
        break;
    }
    std::cout << "Username:\t" << username->GetText() << std::endl;
    auto realname = current_data->FirstChildElement("username");
    if (realname == nullptr)
    {
        std::cout << "realname is null ptr" << std::endl;
        break;
    }
    std::cout << "Real name:\t" << realname->GetText() << std::endl;
    current_data = current_data->NextSibling();
}
while(current_data != last_data);

вот пример рекурсии:

void Recursion(const XMLNode* root, const XMLNode* current_data)
{
    if (current_data == nullptr)
    {
        std::cout << "Child (data) element not found\n" << std::endl;
        return;
    }
    auto username = current_data->FirstChildElement("username");
    if (username == nullptr)
    {
        std::cout << "username is null ptr" << std::endl;
        return;
    }
    std::cout << "Username:\t" << username->GetText() << std::endl;
    auto realname = current_data->FirstChildElement("username");
    if (realname == nullptr)
    {
        std::cout << "realname is null ptr" << std::endl;
        return;
    }
    std::cout << "Real name:\t" << realname->GetText() << std::endl;
    current_data = current_data->NextSibling();
    if(current_data != root->LastChildElement("data"))
    {
        Recursion(root, current_data->NextSibling());
    }
}
READ ALSO
Сборка проекта из под Windows в Linux

Сборка проекта из под Windows в Linux

Очень нужно собрать проект (библиотеки и исполняемые файлы) на Qt в виндовсе на линуксНашел в интернете про сборку с линукса на виндовс, но ничего...

96
С++: приведение типов

С++: приведение типов

Подскажите пожалуйста один вопросик (что-то совсем из головы вылетело):

116
Узнать конец динамического массива

Узнать конец динамического массива

Как можно узнать размер динамического массива, например int* или как получить указатель на его конец

125