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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: XML. Три вопроса. (Решено)  (Прочитано 15069 раз)
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« : Август 14, 2008, 22:49 »

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


Пытаюсь генерить через Qt (DOM модель) XML-файлы, и есть несколько вопросов. Я с XML только во флшевом ActionScript работал, там как-то все просто и сразу работает, видимо из-за динамической типизации. А в Qt что-то осилить не могу..


Вопрос 1. Кто чем пользуется для отладочного вывода в виде XML кода содержимого QDomNode, QDomElement, QDomDocument?

Я себе накорябал такую функцию, но она меня не устраивает, во-первых потому что может выводить только QDomNode и QDomElement, во-вторых потому что как-то странно выполняет свои функции.

Код:
QString xmlnode_to_string(QDomNode xmldata)
{
 QDomDocument tempdoc;

 if(!xmldata.isNull())
  {
   tempdoc.appendChild(xmldata.cloneNode());
   return tempdoc.toString();
  }
 else return "";
}

А странность вот какая. Если выполнить код

Код:
 QDomDocument doc;
 QDomElement elm=doc.createElement("content");
 qDebug() << "New element " << xmlnode_to_string(elm);

то вместо ожидаемого "<content/>" мы видим пустую строку.

Вопрос 2. Почему вместо "<content/>" вышеприведенный код выдает пустую строку?

Ну и еще.

Вопрос 3. Вот простой код


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

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

 // Установка формата версии
 QDomElement formvers=doc.createElement("format");
 formvers.setAttribute("version",1);
 formvers.setAttribute("subversion",1);
 doc.appendChild(formvers);

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

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

При его выполнении получаю файл с содержимым

<format version="1" subversion="1" />

а должен получиться файл

<?xml version="1.0" encoding="UTF-8"?>
<format version="1" subversion="1" />


почему генерируется файл без заголовка?
« Последнее редактирование: Август 15, 2008, 18:15 от xintrea » Записан

Собираю информацию по крупицам
http://webhamster.ru
ритт
Гость
« Ответ #1 : Август 14, 2008, 23:18 »

1. дом всегда зависит от спецификации документа - "оторванные" ветки _нельзя_ дэбажить - читай документацию
1.1. в qt работа с дом реализована _очень_ близко к требованиям спецификации хмл дом - читай спецификацию хмл дом
2. doc.appendChild(elm)  - читай документацию
3. doc.appendChild(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""))  - читай документацию

читай документацию
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



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

1. дом всегда зависит от спецификации документа - "оторванные" ветки _нельзя_ дэбажить - читай документацию

То есть, настоящие гуру XML-ветки не дебажат, потому что нельзя? Ну так в приведеном примере, "оторваная" ветка прикрепляется с глубоким копированием к документу. Документ вроде как можно дебажить через метод toString(). Почему документ получается пустой? Что сделать чтоб в документе появлялась прикрепляемая к нему ветка?


1.1. в qt работа с дом реализована _очень_ близко к требованиям спецификации хмл дом - читай спецификацию хмл дом
2. doc.appendChild(elm)  - читай документацию

Вот я читаю документацию, и нихрена не понимаю, что присходит при выполнении кода

QDomElement elm=doc.createElement("content");

По идее, должен создаться XML-элемент с именем content. Я его (а точнее его копию, ибо передача по значению) скармливаю в дебажную функцию xmlnode_to_string(), в ней переданый элемент прикрепляется к временному документу (причем с глубоким копированием). И содержимое этого временного документа выводится на экран. Однако, вопреки ожиданию увидеть "<content/>", вижу пустую строку. В каком месте рассуждений ошибка?

Да, делать doc.appendChild(elm) мне не нужно. Я хочу только понять, как дебажить/клеить элементы/ноды, пускай и "оторванные". Это нужно понять, само собой, не только для дебага.


3. doc.appendChild(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""))  - читай документацию

Угу, вместо

doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");

надо было писать

doc.appendChild(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""))

Тока как-то неестественно запихивать документ в документ. Ведь XML-документ состоит из XML-элементов, а не из XML-документов.


читай документацию

Мда, троллям еще над документацией надо работать и работать. Сейчас она больше похожа на линуховые маны, в которых минимальными словами описаны опции и больше ничего. До уровня доков Adobe по ActionScript, или там доков Microsoft по VisualBasic, или даже до доки в досовом Борланд C, в которых практически на каждую функцию сделан пример, дока Qt не дотягивает. Хорошо хоть в начале разделов дают небольшие примеры, без них бы Qt был вообще неизучаем. А без примеров в две-три строки на каждую описываемую функцию, пионерам сложно.
« Последнее редактирование: Август 15, 2008, 14:27 от xintrea » Записан

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

через toString ты получаешь документ обработанный хмл процессором т.е. результат:
Код:
  QString xmlstr = "<?xml version=\"1.0\"?><!DOCTYPE letter [<!ENTITY title \"title text\">]>\
   <letter>&title;</letter>";
 
  QDomDocument doc;
  doc.setContent(xmlstr, true);
 
  qDebug() << doc.toString();
выведет:
Код:
<?xml version='1.0'?>
<!DOCTYPE letter>
<letter>title text</letter>
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #4 : Август 15, 2008, 14:23 »

через toString ты получаешь документ обработанный хмл процессором т.е. результат:
Код:
  QString xmlstr = "<?xml version=\"1.0\"?><!DOCTYPE letter [<!ENTITY title \"title text\">]>\
   <letter>&title;</letter>";
 
  QDomDocument doc;
  doc.setContent(xmlstr, true);
 
  qDebug() << doc.toString();
выведет:
Код:
<?xml version='1.0'?>
<!DOCTYPE letter>
<letter>title text</letter>

Спасибо, конечно.. А как это относится к вопросам выше?
Записан

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

если спросил, _слушай_ ответ, а?
итак, ещё раз:
1., 2.
Код:
QDomDocument doc;
 QDomElement elm=doc.createElement("content"); // - "оторванная" ветка
 doc.appendChild(elm); // - нормальная ветка
 qDebug() << "New element " << xmlnode_to_string(elm);

3. createProcessingInstruction создаёт не документ, а ветку! как и в 1-2 - если ты не прикрепил ветку к документу, ветки нет - она оторвана, а оторванные ветки не имеют отношения к документу, а посему невалидны. а раз невалидны, то и не дебажатся

4. приведи ссылку на хорошие доки по хмл в том же ас или вб. если без примерчика 2 + 2 = 4 в голове ничего не проясняется, не лезь в плюсы

5. моё предвзятое мнение: сравнение тролльтеха с m$ (пусть и косвенное) - флуд. флудеров на этом форуме банят. /* считай это предупреждением */
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #6 : Август 15, 2008, 18:14 »

если спросил, _слушай_ ответ, а?
итак, ещё раз:
1., 2.
Код:
QDomDocument doc;
 QDomElement elm=doc.createElement("content"); // - "оторванная" ветка
 doc.appendChild(elm); // - нормальная ветка
 qDebug() << "New element " << xmlnode_to_string(elm);

Хмм... Что в ^^^этом куске кода является _ответом_?


В любом случае, проблема оказалась не в "оторваных" и "нормальных" ветках. А в особенности инициализации документа. Оказывается, документ, который создается командой типа QDomDocument tempdoc, является при создании пустым, и к нему невозможно прикрепить ни "оторванную", ни "нормальную" ветку.

Чтобы ветка прикреплялась, документ должен быть ненулевой. Либо документ может быть нулевым, но прикрепляемая ветка должна быть создана через метод createElement() именно этого же документа.

Пояснения на примере

Код:
 // Так НЕ работает
 qDebug() << "\n It is NOT work";
 QDomDocument doca1;
 QDomElement elma=doca1.createElement("content"); // Создаем элемент
 QDomDocument doca2; //
 doca2.appendChild(elma); // Прикрепляем элемент к ПУСТОМУ документу
 qDebug() << "Document a2 " << doca2.toString();

 // Так работает
 qDebug() << "\n It is work";
 QDomDocument docb1;
 QDomElement elmb=docb1.createElement("content"); // Создаем элемент
 QDomDocument docb2("debugdoc");
 docb2.appendChild(elmb); // Прикрепляем элемент к НЕПУСТОМУ документу (т.к. при создании был передан DOCTYPE "debugdoc")
 qDebug() << "Document b2 " << docb2.toString();

 // Так работает
 qDebug() << "\n It is work";
 QDomDocument docc;
 QDomElement elmc=docc.createElement("content"); // Создаем элемент
 docc.appendChild(elmc); // Прикрепляем элемент к ПУСТОМУ документу, но элемент был создан через createElement() данного документа
 qDebug() << "Document c " << docc.toString();

Результат выполнения этого кода такой

Код:
 It is NOT work
Calling appendChild() on a null node does nothing.
Document a2  ""

 It is work
Document b2  "<!DOCTYPE debugdoc>
<content/>"

 It is work
Document c  "<content/>"

Подумав и поэкспериментировав еще немного, начинаешь понимать, что третий вариант кода трактуется выше по тексту неправильно. Не обязательно "прикрепляемая ветка должна быть создана через метод createElement() именно этого же документа". Происходит кое-что другое. А происходит вот что - при вызове метода createElement(), несмотря на то, что создаваемый элемент является "оторванным" и существует "сам по себе", документ, у которого был вызван createElement(), перестает быть нулевым.

Проверим это на примере

Код:
 // Так работает
 qDebug() << "\n It is  work";
 QDomDocument doc1;
 QDomElement elm1=doc1.createElement("content"); // Создаем элемент
 QDomDocument doc2; //
 QDomElement elm2=doc2.createElement("stub"); // Создаем элемент-вспомогалку, который является "оторванным", но создание которого повлияло на doc2 и сделало doc2 НЕПУСТЫМ
 doc2.appendChild(elm1); // Прикрепляем элемент к ТИПА_ПУСТОМУ документу
 qDebug() << "Document " << doc2.toString();

Результат выполнения этого кода

Код:
 It is  work
Document  "<content/>"


Собирая все в кучу, понимаем как можно сделать дебаговый вывод (любого "оторванного" или там "неоторванного") элемента.

Вначале у нас была функция, которая тупо не выводила содержимого узлов. Не потому что узлы были "оторваны" или "неоторваны", а просто - она не выводила содержимого узлов вообще. Как теперь выясняется, проблемы была в том, что документ tempdoc нуливой, и к нему ветка прицепиться не может. Напоминаю код

Код:
QString xmlnode_to_string(QDomNode xmldata)
{
 QDomDocument tempdoc;

 if(!xmldata.isNull())
  {
   tempdoc.appendChild(xmldata.cloneNode());
   return tempdoc.toString();
  }
 else return "";
}

Какую бы ветку в эту функцию не скармливай, результат будет такой

Код:
Calling appendChild() on a null node does nothing.
""


Попробуем модифицировать эту функцию, и просто заменим строку QDomDocument tempdoc; на  QDomDocument tempdoc("debugdoc");. В результате, какую бы ветку мы не передали, "оторванную" или "неоторванную", ее содержимое мы увидем, но не в совсем нужной для нас форме. Код

Код:
 QDomElement elm=doc.createElement("content"); // - "оторванная" ветка
 qDebug() << "New element " << xmlnode_to_string(elm);

Покажет вот что

Код:
New element  "<!DOCTYPE debugdoc>
<content/>"

Узел <!DOCTYPE debugdoc> явно мешает. Тогда приводим функцию вот к такому виду

Код:
QString xmlnode_to_string(QDomNode xmldata)
{
 QDomDocument tempdoc;

 // Создаем элемент-вспомогалку, который нигде не используется, но создание которого
 // влияет на tempdoc, делая этот докумен ненулевым
 QDomElement tempelm=tempdoc.createElement("stub");

 if(!xmldata.isNull())
  {
   tempdoc.appendChild(xmldata.cloneNode());
   return tempdoc.toString();
  }
 else return "";
}

И такая функция при вызове кода

Код:
 QDomElement elm=doc.createElement("content"); // - "оторванная" ветка
 qDebug() << "New element " << xmlnode_to_string(elm);

Покажет то что нужно

Код:
New element  "<content/>"


3. createProcessingInstruction создаёт не документ, а ветку! как и в 1-2 - если ты не прикрепил ветку к документу, ветки нет - она оторвана, а оторванные ветки не имеют отношения к документу, а посему невалидны. а раз невалидны, то и не дебажатся

Как видно, дебажатся.


4. приведи ссылку на хорошие доки по хмл в том же ас или вб. если без примерчика 2 + 2 = 4 в голове ничего не проясняется, не лезь в плюсы

Ссылка http://livedocs.adobe.com/flash/9.0/ActionScriptLangRefV3/, ознакомьтесь краем глаза. А вообще хорошие доки по XML в составе документации на язык программирования или библиотеку ненужны. Ненадо путать понятия. В документации на язык программирования или библиотеку должны быть хорошо задокументированы функции работы с XML. А это в Qt доке сделано недостаточно полно. Заметте, про ms ни слова. И не пугайте неофитов плюсами, мне то пофигу, а есть такие люди которые отвернутся от плюсов и Qt только потому, что им Константин посоветовал не лезть.
Записан

Собираю информацию по крупицам
http://webhamster.ru
ритт
Гость
« Ответ #7 : Август 15, 2008, 19:29 »

если я правильно помню из спецификации, валидный xml-документ должен содержать document type declaration (doctype). иначе, даже если документ отвечает требованиям well-formed, он всё-равно остаётся невалидным...
в документации по QDomDocument сказано:
Цитировать
QDomDocument::QDomDocument ()
Constructs an empty document.
QDomDocument::QDomDocument ( const QString & name )
Creates a document and sets the name of the document type to name.
QDomDocument::QDomDocument ( const QDomDocumentType & doctype )
Creates a document with the document type doctype.
как бы в подтверждение...однако, я сейчас пробегусь по спецификации глазами и попробую найти/вспомнить где я видел подобное утверждение
Записан
ритт
Гость
« Ответ #8 : Август 15, 2008, 19:44 »

угу, нашёл - http://www.w3.org/TR/xml/#sec-prolog-dtd

каюсь, в коде примера не обратил на то внимания
сейчас заглянул в свой генератор списков - вот примерный код создания документа:
Код:
	QDomDocument doc("myxmldoc");

QDomProcessingInstruction instr = doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\"");
doc.appendChild(instr);

QDomElement root = doc.createElement("root");
doc.appendChild(root);

//snip
IBResult db_res = IBElement::list(_filter, _sorting);
while(db_res.next())
{
QDomElement element = doc.createElement("element");
element.setAttribute("id", db_res.value("ID").toString());
root.appendChild(element);
}

также ссылки по теме:
* http://www.w3.org/TR/REC-DOM-Level-1/
* http://www.w3.org/TR/DOM-Level-2-Core/

зы. на ас3 мне когда-то приходилось писать. да - документация относительно неплохая - сниппетов для ленивых полно (правда, их невозможно ни выключить, ни свернуть - порой замучиваешься что-то найти), но работа с хмл реализована через зад - как в ас2, так и в ас3...да и сам язык для дЕзайнеров. /* радует лишь возможность обновлять эти мегатонны документации через сеть */
Записан
xintrea
Супер активный житель
*****
Offline Offline

Сообщений: 754



Просмотр профиля WWW
« Ответ #9 : Август 15, 2008, 20:53 »

Ну как бы в описании метода toString() не указывается, что для преобразования в строку документа, DOM-представление обязательно должно быть валидным.

Кусок из русской доки, арфаграфия аффтарская

Цитировать
QString QDomDocument::toString ( int indent = 1 ) const

Переводет анализируемый документ обратно в его текстовое представление.
Эта фукнция использует indent для определения объема пространства отступа для подэлементов.



Меня больше беспокоит другое.

1. Что же действительно присходит при выполнении кода вида

Код:
QDomDocument doc;
QDomElement elm = doc.createElement("element");
?

Почему на документ doc происходит влияние через createElement(), и он уже не является null node, хотя все так же ничего не содержит?

Почему у троллей в документации вышеприведенный код повторяется как мантра? Потому что они знают об этой особенности. Но по неизвестным причинам не описывают подробностей.


2. В связи с вышенаписанным, не получится ли так, что в новой подверсии Qt такое поведение будет изменено? Например, doc.createElement("element") перестанет влиять на документ doc, и doc будет оставаться в виде null node? И тогда весь код, который был написан со знанием этой особенности станет невалидным?

Записан

Собираю информацию по крупицам
http://webhamster.ru
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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