Russian Qt Forum

Qt => XML => Тема начата: xintrea от Август 16, 2008, 23:59



Название: Не могу сделать простую вещь - добавить подэлемент в дерево.
Отправлено: xintrea от Август 16, 2008, 23:59
Здравствуйте!


Вторые сутки бъюсь на простой проблемой. Кратко задача такая.

Есть QDomElement, содержащий некоторое DOM дерево. Надо - добавить в него один элемент (на первый уровень вложения), приклеить получившийся элемент к пустому документу, и сохранить документ в файл. Вот болванка, дальше мы бодем изменять в ней один блок кода

Код:
 // Коструирование DOM документа для записи в файл
 QDomDocument doc;

 // Установка заголовка
 doc.appendChild(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""));

 // Получение DOM дерева хранимых данных (это моя функция, рабочая)
 QDomElement elm=nodemodel->export_fullmodeldata_to_dom(nodemodel->rootItem);

 // Добавление формата версии к элементу хранящему DOM дерево хранимых данных
 QDomElement formvers=doc.createElement("format");
 formvers.setAttribute("version",CURRENT_FORMAT_VERSION);
 formvers.setAttribute("subversion",CURRENT_FORMAT_SUBVERSION);
 elm.appendChild(formvers.cloneNode());

 // Добавление дерева DOM хранимых данных к документу
 doc.appendChild(elm);

 qDebug() << "Doc document for write " << doc.toString();

 // Запись DOM данных в файл
 QString filename="temp.xml";
 QFile wfile(filename);
 if (!wfile.open(QIODevice::WriteOnly | QIODevice::Text)){qDebug() << "Cant open file ";exit(1);}
 QTextStream out(&wfile);
 out.setCodec("UTF-8");
 out << doc.toString();

В результате мы имеем

Код:
Doc document for write  "<?xml version="1.0" encoding="UTF-8"?>
<content>
 </node>
   <record dir="0000000100" id="49" name="Тушканчик" file="text.txt" />
 </node>
 <format version="1" subversion="1" />
</content>
"
*** glibc detected *** ./mytetra: corrupted double-linked list: 0x087e6aa8 ***
======= Backtrace: =========
/lib/tls/i686/cmov/libc.so.6[0xb73d8b2a]
/lib/tls/i686/cmov/libc.so.6[0xb73dae38]
/lib/tls/i686/cmov/libc.so.6[0xb73dbef5]
/lib/tls/i686/cmov/libc.so.6(realloc+0xfe)[0xb73de08e]
/usr/lib/libQtCore.so.4(_Z8qReallocPvj+0x24)[0xb7621c38]
/usr/lib/libQtCore.so.4(_ZN9QListData7reallocEi+0x68)[0xb7647bc0]
/usr/lib/libQtCore.so.4(_ZN9QListData6appendERKS_+0xc1)[0xb7647e6f]
/usr/lib/libQtGui.so.4[0xb78a7c5c]
/usr/lib/libQtGui.so.4(_ZN12QApplication10allWidgetsEv+0x98)[0xb789ed68]
/usr/lib/libQtGui.so.4(_ZN12QApplication15topLevelWidgetsEv+0x28)[0xb789eda6]
/usr/lib/libQtGui.so.4(_ZN19QApplicationPrivate26_q_tryEmitLastWindowClosedEv+0x26)[0xb789ee8c]
/usr/lib/libQtGui.so.4(_ZN12QApplication11qt_metacallEN11QMetaObject4CallEiPPv+0x114)[0xb78a145e]
/usr/lib/libQtCore.so.4(_ZN14QMetaCallEvent13placeMetaCallEP7QObject+0x34)[0xb76ed588]
/usr/lib/libQtCore.so.4(_ZN7QObject5eventEP6QEvent+0x13f)[0xb76f28ef]
/usr/lib/libQtCore.so.4(_ZN16QCoreApplication5eventEP6QEvent+0x47)[0xb76df84b]
Aborted (core dumped)4(_Z


Если закомментировать код

Код:
 // Добавление формата версии к элементу хранящему DOM дерево хранимых данных
 QDomElement formvers=doc.createElement("format");
 formvers.setAttribute("version",CURRENT_FORMAT_VERSION);
 formvers.setAttribute("subversion",CURRENT_FORMAT_SUBVERSION);
 elm.appendChild(formvers.cloneNode());

То ошибки не возникает. Логично предполагаю, что проблема в этом куске кода, что-то там добавляется некорректно.

Начинаю экспериментировать. Пробую так

Код:
// Добавление формата версии к элементу хранящему DOM дерево хранимых данных
 QDomElement formvers=another.createElement("format"); // Элемент на основе временного документа
 formvers.setAttribute("version",CURRENT_FORMAT_VERSION);
 formvers.setAttribute("subversion",CURRENT_FORMAT_SUBVERSION);
 elm.appendChild(formvers.cloneNode());

Ошибки нет, но узел <format version="1" subversion="1" /> не появляется. Пробовал еще по-разному. Результат один и тот же - ошибки нет, но узла <format version="1" subversion="1" /> тоже нет. Вот еще как пробовал

Код:
// Добавление формата версии к элементу хранящему DOM дерево хранимых данных
 QDomElement formvers;
 formvers.setTagName("format");
 formvers.setAttribute("version",CURRENT_FORMAT_VERSION);
 formvers.setAttribute("subversion",CURRENT_FORMAT_SUBVERSION);
 elm.appendChild(formvers.cloneNode());

И еще пробовал варианты кода без cloneNode() в последней строке. Ничего не помогает - ошибки нет, но и узла <format version="1" subversion="1" /> тоже нет.


Я уже не знаю что делать. На просторах интернета ничего внятного не нашел. Кроме того, что подобная ошибка происходит в режиме компиляции C++ (не в чистом C). На русских ресурсах такую ошибку видел только один человек. У боржуев - ошибка популярна, возникает в GTK+, в каких-то HTML-парсерах, в Qt. Но с моим знанием англицкого понять что к чему весьма трудно.


Вопрос - что делать то? Задачка ведь простая, но такие сложности выше моего понимания. Кто что может сказать, возможно у когото есть подобный опыт.


Название: Re: Не могу сделать простую вещь - добавить подэлемент в дерево.
Отправлено: ритт от Август 17, 2008, 01:07
а попробуй doc.appendChild(elm) выполнить до QDomElement elm=nodemodel->export_fullmodeldata_to_dom(nodemodel->rootItem) ?
ещё можешь попробовать передавать ссылку на QDomDocument в export_fullmodeldata_to_dom(...)
я с таким странным поведением ни разу не сталкивался - у меня импорт/экспорт хмл работает вообще без неожиданностей (правда, никогда не создаю временных нод и при генерировании документа предпочитаю обходиться без клонирования)

зы: вроде ж решили уже пользоваться валидными документами? :)
Код:
QDomDocument doc("doc");


Название: Re: Не могу сделать простую вещь - добавить подэлемент в дерево.
Отправлено: xintrea от Август 17, 2008, 12:02
Да, помогло две вещи.

1. Создавать валидный документ с указанием DOCTYPE,

т. е. вместо
Код:
QDomDocument doc();
писать
Код:
QDomDocument doc("doc");


2. Прилеплять ветку без глубокого копирования,

т. е. вместо
Код:
elm.appendChild(formvers.cloneNode());
писать
Код:
elm.appendChild(formvers);