Russian Qt Forum
Май 23, 2024, 08:04 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Ступор. Перебор одноуровненых элементов в документе.  (Прочитано 6658 раз)
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« : Июль 31, 2008, 23:18 »

Здравствуйте!


Все время, для дебажного просмотра содержимого элемента в XML-виде, я пользовался такой конструкцией.

Код:
 // e - это QDomElement
 QDomDocument t("t");
 t.appendChild(e);
 qDebug() << "Element " << t.toString();

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

Задачка: имеем документ с одноуровневыми элементами. В XML формате он записывается так

Код:
<element_1/>
<element_2/>
<element_3/>

Мне его нужно обежать и вывести имена всех элементов на экран. 

Вот нормально работающий код

Код:
 // Конструируем документ
 QDomDocument rectab;

 QDomElement e1=rectab.createElement("element_1");
 rectab.appendChild(e1);
 QDomElement e2=rectab.createElement("element_2");
 rectab.appendChild(e2);
 QDomElement e3=rectab.createElement("element_3");
 rectab.appendChild(e3);

 // Проверяем что получилось
 qDebug() << "Rectab " << rectab.toString();

 // Обегаем все элементы
 QDomNode n = rectab.firstChild();
 while(!n.isNull())
  {
   QDomElement e = n.toElement(); // пробуем преобразовать узел в элемент.
   if(!e.isNull())
    {
     qDebug() << "Element " << e.tagName(); // выводим имя узла
    }
   n = n.nextSibling();
  }

Он реально пробегает по всем элементам, и выводит их названия

Код:
Rectab  "<element_1/>
<element_2/>
<element_3/>
"
Element  "element_1"
Element  "element_2"
Element  "element_3"

А вот неправильно работающий цикл (стрелками показаны строчки которые были изменены относительно предыдущего примера кода)

Код:
 // Обегаем все элементы
 QDomNode n = rectab.firstChild();
 while(!n.isNull())
  {
   QDomElement e = n.toElement(); // пробуем преобразовать узел в элемент.
   if(!e.isNull())
    {
->    QDomDocument t("t");
->    t.appendChild(e);
->    qDebug() << "Element " << t.toString(); // Выводим элемент на экран
    }
   n = n.nextSibling();
  }

Который обегает только первый элемент

Код:
Rectab  "<element_1/>
<element_2/>
<element_3/>
"
Element  "<!DOCTYPE t>
<element_1/>"

То есть, элемент 2 и 3 не видится.

Почему так происходит? По какой причине узел n теряет связи со своими последующими узлами в этом случае? Я n при выводе вообще не трогаю, использую временный объект t, в который вставляю временный объект e (делаю это чтоб увидеть XML-код). Почему же данный цикл не работает?
Записан

Собираю информацию по крупицам
http://webhamster.ru
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #1 : Июль 31, 2008, 23:31 »

Узел очевидно просто мигрировал с одного документа в другой

Если сделать так

Код:
....
QDomDocument t("t");
t.appendChild(e.cloneNode());
qDebug() << "Element " << t.toString(); // Выводим элемент на экран
....

поидее должно работать.
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #2 : Август 01, 2008, 10:22 »

Таки да, cloneNode() помогло...

Но факт остается фактом - в коде

Код:
 QDomDocument t("t");
 t.appendChild(e);
 qDebug() << "Element " << t.toString();

нет и упоминания об объекте n, который в результате "мигрировал с одного документа в другой". Максимум что есть - передача производного объекта e в функцию appendChild(), причем передача по значению, а не по ссылке. А если идет передача по значению, объект e меняться не должен. В результате работы данного кода только объект t должен измениться и начать указывать своим узлом на временный оъект e. А объект n тут вообще не затрагивается.

В какой момент происходит миграция объекта n с одного документа в другой?

Блин, я уже боюсь пользоваться Qt с такими залипухами... Вместо работы с грабли на граблю наступаю.
Записан

Собираю информацию по крупицам
http://webhamster.ru
spirit
Гость
« Ответ #3 : Август 01, 2008, 10:30 »

Таки да, cloneNode() помогло...

Но факт остается фактом - в коде

Код:
 QDomDocument t("t");
 t.appendChild(e);
 qDebug() << "Element " << t.toString();

нет и упоминания об объекте n, который в результате "мигрировал с одного документа в другой". Максимум что есть - передача производного объекта e в функцию appendChild(), причем передача по значению, а не по ссылке. А если идет передача по значению, объект e меняться не должен. В результате работы данного кода только объект t должен измениться и начать указывать своим узлом на временный оъект e. А объект n тут вообще не затрагивается.

В какой момент происходит миграция объекта n с одного документа в другой?

Блин, я уже боюсь пользоваться Qt с такими залипухами... Вместо работы с грабли на граблю наступаю.
как только выполнил эти операции
Код:
 QDomDocument t("t");
 t.appendChild(e);
 qDebug() << "Element " << t.toString();
в первой строке создается новый документ,
во второй елемент из другого элемента устанавливается в новый.
нужно лонировать элемент, чтобы такого не происходило.
Записан
Alex03
Гость
« Ответ #4 : Август 01, 2008, 10:36 »

Цитировать
QDomElement & QDomElement::operator= ( const QDomElement & x )

Assigns x to this DOM element.

The data of the copy is shared (shallow copy): modifying one node will also change the other. If you want to make a deep copy, use cloneNode().

Цитировать
QDomNode QDomNode::appendChild ( const QDomNode & newChild )

Appends newChild as the node's last child.

If newChild is the child of another node, it is reparented to this node. If newChild is a child of this node, then its position in the list of children is changed.

If newChild is a QDomDocumentFragment, then the children of the fragment are removed from the fragment and appended.

If newChild is a QDomElement and this node is a QDomDocument that already has an element node as a child, newChild is not added as a child and a null node is returned.

Calling this function on a null node(created, for example, with the default constructor) does nothing.

The DOM specification disallow inserting attribute nodes, but due to historical reasons QDom accept them nevertheless.
Записан
ритт
Гость
« Ответ #5 : Август 01, 2008, 18:02 »

грабли опять же от нечтения документации
фактически ты отнимаешь элемент у документа и вставляешь в новый документ, откуда и выводишь на дэбаг, НО сиблингов в этом документе для интересующего элемента ровно 0
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.046 секунд. Запросов: 19.