crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

 
Ответить в данную темуНачать новую тему
> Пройтись по всем нодам QDomDocument без рекурсивных функций
RazrFalcon
  опции профиля:
сообщение 13.4.2013, 23:34
Сообщение #1


Zombie Mod
*****

Группа: Участник
Сообщений: 1654
Регистрация: 24.5.2010
Из: Харьков
Пользователь №: 1752

Спасибо сказали: 64 раз(а)




Репутация:   212  


Обычный вариант с рекурсией:
void MyClass::process(QDomNode node)
{
    QDomNodeList nodeList = node.childNodes();
    for (int i = 0; i < nodeList.count(); ++i) {
        // some stuff
        if (node.childNodes().at(i).hasChildNodes())
            process(nodeList.at(i));
    }
}

Можно ли, как-то, это обернуть в while, что бы можно было внутри какой-либо функции пройтись по всем элементам. А то сейчас приходиться отдельную функцию заводить...

Сообщение отредактировал RazrFalcon - 13.4.2013, 23:35
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 14.4.2013, 15:25
Сообщение #2


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


переход от рекурсии к итерации производится через создание собственного стека FILO (при рекурсии используется стек вызовов)

инициализация стека: кладём в стек первый (первые) элемент;

while(стек не пуст)
{
     извлечь текущий элемент из стека -> curr;

     исследование и обработка curr , в процессе обработки в стек заносятся ещё элементы;
}



Цитата
что бы можно было внутри какой-либо функции пройтись по всем элементам.

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

как вариант - работа с предикатом, шаблонная процедура

Сообщение отредактировал Алексей1153 - 14.4.2013, 15:31
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
RazrFalcon
  опции профиля:
сообщение 15.4.2013, 13:58
Сообщение #3


Zombie Mod
*****

Группа: Участник
Сообщений: 1654
Регистрация: 24.5.2010
Из: Харьков
Пользователь №: 1752

Спасибо сказали: 64 раз(а)




Репутация:   212  


Да, такой способ я видел, но увы QDomDocument не умеет переходить на следующий элемент.
По этому такой вариант не работает:
    QDomNode node = m_doc.firstChild();
    while (!node.isNull()) {
        // some stuff
        node = node.nextSibling();
    }
Так как node.nextSibling не умеет проверять дочерние элементы. А так как структура xml мне заранее не известна, то не ясно как пройтись по дереву таким способом.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 15.4.2013, 16:57
Сообщение #4


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


QDomNodeList list;

list.append (root_node);
while (!list.empty ()) {
    QDomElement el = list.takeAt (0).toElement ();
    do_stuff (el);
    list.append (el.childNodes ());
};

?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Алексей1153
  опции профиля:
сообщение 15.4.2013, 18:57
Сообщение #5


фрилансер
******

Группа: Участник
Сообщений: 2939
Регистрация: 19.6.2010
Из: Обливион
Пользователь №: 1822

Спасибо сказали: 215 раз(а)




Репутация:   34  


RazrFalcon, node.nextSibling(); находит соседний тег , таким образом ты перебираешь теги одного уровня в текущей "области видимости". Каждый тег помещаешь в стек. Новая итерация извлекает элемент и идёт уже по его чайлдам. Понимаешь фишку ? Поэтому в начале работы алгоритма важно инициализировать стек элементами первого уровня - ещё перед заходом в основной цикл перебора стека

кстати, nextSibling() без указания имени ищет любой следующий тег этого же уровня (скорее всего тег будет тот, что идёт в реальном тексте XML , но на это не стоит полагаться, мне кажется - не знаю, что на этот счёт говорит стандарт. Я всегда предполагаю, что порядок выбора может быть случайным)

если указать имя предыдущего элемента, найдётся элемент с таким же именем:

node.nextSibling(node.nodeName());


хотя, в твоём случае, с неизвестным контентом, это, наверное, не особо пригодится
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
RazrFalcon
  опции профиля:
сообщение 20.4.2013, 20:23
Сообщение #6


Zombie Mod
*****

Группа: Участник
Сообщений: 1654
Регистрация: 24.5.2010
Из: Харьков
Пользователь №: 1752

Спасибо сказали: 64 раз(а)




Репутация:   212  


Немного переделал вариант от lanz, так как его не работал.
+ без доп функции пока никак...

QList<QDomNode> MyClass::childNodeList(QDomNode parent)
{
    QList<QDomNode> outList;
    QDomNodeList tmpList = parent.childNodes();
    for (int i = 0; i < tmpList.count(); ++i)
        outList << tmpList.at(i);
    return outList;
}

void MyClass::someClass()
{
    QList<QDomNode> list = childNodeList(m_svgNode);
    while (!list.empty()) {
        QDomElement currElem = list.takeAt(0).toElement();

        // stuff

        list << childNodeList(currElem);
    }
}


Вроде бы работает верно, и довольно короткая запись.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
lanz
  опции профиля:
сообщение 22.4.2013, 10:01
Сообщение #7


Старейший участник
****

Группа: Участник
Сообщений: 690
Регистрация: 28.12.2012
Пользователь №: 3660

Спасибо сказали: 113 раз(а)




Репутация:   8  


Это я конечно маху дал, думал что QDomNodeList это typedef вроде QObjectList.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

Быстрый ответОтветить в данную темуНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0




RSS Текстовая версия Сейчас: 20.4.2024, 10:31