Как получить XML код из DOM представленияКаждый, кто начинает разбираться с XML в Qt и начинает работать с DOM представлением XML данных, быстро обнаруживает, что в Qt отсутсвуют удобные инструменты для получения XML кода из DOM представления. Практически, получить XML код из DOM представления можно только для
документа. А вот чтобы проверить содержимое отдельного
узла или
элемента, программисту приходится дописывать дополнительный код.
В этом уроке приведена готовая функция, которой можно скармливать любые XML-узлы в виде объектов QDomNode (QDomDocument, QDomElement...). На выходе функция возвращает строку с XML-кодом данного объекта.В написании такой функции, впринципе, нет ничего сложного. Основная идея в том, чтобы прикрепить узлы (или элементы) к пустому документу, и получить XML-код такого временного документа через метод
toString(). Однако воникает проблема - нужно получить пустой документ, у которого не будет ни одного узла (элемента), и прикрепить у нему наши узлы.
Дело осложняется тем, что к чистому, только что созданному документу прикрепить узлы невозможно. Помните об этом, когда работаете с DOM-объектами! Обязательно нужно, чтобы документ был ненулевым. А это значит, что в результирующей строке будет расположен (помимо XML-кода переданного DOM-элемента) XML-код DOM-представления, который делает документ ненулевым. А лишний XML-код нам ненужен.
Я много времени потратил на то, чтобы разобраться, в какой момент XML DOM-документ становится "ненулевым", и с ним можно начинать работать. Оказывается, если с помощью документа создать отдельный элемент, например через метод createElement(), то, несмотря на то, что созданный элемент не будет иметь отношения к документу (с помощью которого он всего лишь создан), документ хоть и останется пустым, но будет уже "ненулевым". И с ним можно начинать работать.
Не буду дальше размусоливать проблему, и просто приведу код функции. Её можно просто вставить в свой проект и пользоваться.
C++ (Qt)
// Наша замечательная функция
QString domxmlToString(QDomNode xmldata)
{
// Если узел представляет собой полностью документ
if(xmldata.isDocument())
{
// Значит этот узел можно напрямую преобразовать
// в документ, а потом в XML строку
return xmldata.toDocument().toString();
}
else
{
// Иначе, узел не является документом, и чтобы получить
// его текстовое представление, надо узел прикрепить к пустому документу
QDomDocument tempdoc;
// Создаем элемент-вспомогалку, который нигде не используется, но создание которого
// влияет на tempdoc, делает этот документ ненулевым, оставляя его пустым
// (Попробуйте закомментировать эту строку, и посмотрите что получится)
QDomElement tempelm = tempdoc.createElement("stub");
// Если переданный в функцию элемент содержит данные
if(!xmldata.isNull())
{
// Элемент прикрепляется к пустому (но ненулевому!) документу
tempdoc.appendChild(xmldata.cloneNode());
// И результирующий DOM документ преобразуется в XML строку
return tempdoc.toString();
}
else return ""; // Если данных в элементе небыло, возвращается пустая строка
}
}
А вот как можно использовать эту функцию:
C++ (Qt)
// Конструируем документ
QDomDocument rectab;
QDomElement e1=rectab.createElement("element1");
rectab.appendChild(e1);
QDomElement e2=rectab.createElement("element2");
e1.appendChild(e2);
QDomElement e22=rectab.createElement("element22");
e22.setAttribute("id","100");
e22.setAttribute("book","C++ for proffesional");
e2.appendChild(e22);
QDomElement e3=rectab.createElement("element3");
e1.appendChild(e3);
// Проверяем что получилось, можем распечатать полный XML документ
qDebug() << domxmlToString(rectab);
// А можем распечатать и часть XML документа, представленную
// в виде QDomNode или других производных классов
qDebug() << domxmlToString(e2);
Данный код выведет в консоль как содержимое полного документа, так и содержимое отдельного элемента
"<element1>
<element2>
<element22 book="C++ for proffesional" id="100" />
</element2>
<element3/>
</element1>"
"<element2>
<element22 book="C++ for proffesional" id="100" />
</element2>"
Проверено на Qt 4.3.0 и 4.4.1, Linux.
Лирическое отступлениеЕсли в функции domxmlToString() мы закомментируем "бессмысленную" строчку
QDomElement tempelm = tempdoc.createElement("stub");то в момент выполнения программы будет выдано предупреждение
Calling appendChild() on a null node does nothing.и, соответсвенно, XML код элемента e2 не сгенерируется.