Потоковая обработка XML
Начиная с версии 4.3, Qt предоставляет два новых класса для чтения и записи XML: QXmlStreamReader и QXmlStreamWriter.
Классы QXmlStreamReader и QXmlStreamWriter представлены в Qt 4.3 и более поздних версиях. Потоковый ридер отображает XML-документ как поток токенов. Это отличается от SAX, так как приложения SAX предоставляют обработчики для получения XML-событий от парсера, в то время как QXmlStreamReader управляет циклом, извлекая токены из ридера по мере необходимости. Такой подход с извлечением позволяет создавать парсеры рекурсивного спуска, что позволяет разделить код разбора XML на разные методы или классы.
QXmlStreamReader — это парсер хорошо сформированного XML 1.0, исключающий внешние сущности. Следовательно, данные, предоставляемые потоковым ридером, соответствуют критериям W3C для хорошо сформированного XML, пока не произойдёт ошибка. В противном случае, можно использовать такие функции, как atEnd(), error() и hasError(), чтобы проверить и просмотреть ошибки.
Пример реализации QXmlStreamReader представлен в XbelReader в Примере закладок QXmlStream, который оборачивает QXmlStreamReader. Конструктор принимает treeWidget в качестве параметра, и у класса есть специфичные для Xbel функции:
XbelReader(QTreeWidget *treeWidget);
...
void readXBEL();
void readTitle(QTreeWidgetItem *item);
void readSeparator(QTreeWidgetItem *item);
void readFolder(QTreeWidgetItem *item);
void readBookmark(QTreeWidgetItem *item);
QTreeWidgetItem *createChildItem(QTreeWidgetItem *item);
QXmlStreamReader xml;
QTreeWidget *treeWidget;
...Функция read() принимает QIODevice и устанавливает его с помощью setDevice(). Функция raiseError() используется для отображения пользовательского сообщения об ошибке, указывающего на то, что версия файла неверна.
bool XbelReader::read(QIODevice *device)
{
xml.setDevice(device);
if (xml.readNextStartElement()) {
if (xml.name() == QLatin1String("xbel")
&& xml.attributes().value(versionAttribute()) == QLatin1String("1.0")) {
readXBEL();
} else {
xml.raiseError(QObject::tr("The file is not an XBEL version 1.0 file."));
}
}
return !xml.error();
}Дополнительным классом к QXmlStreamReader является QXmlStreamWriter, который предоставляет XML-запись с простым потоковым API. QXmlStreamWriter работает с QIODevice и имеет специализированные функции для всех XML-токенов или событий, которые вы хотите записать, такие как writeDTD(), writeCharacters(), writeComment() и так далее.
Для записи XML-документа с помощью QXmlStreamWriter, вы начинаете документ с помощью функции writeStartDocument() и заканчиваете его с помощью writeEndDocument(), которая неявно закрывает все оставшиеся открытые теги. Теги элементов открываются с помощью writeStartDocument() и следуют за writeAttribute() или writeAttributes(), содержимым элемента, а затем writeEndDocument(). Также можно использовать writeEmptyElement() для записи пустых элементов.
Содержимое элемента включает символы, ссылки на сущности или вложенные элементы. Содержимое можно записать с помощью writeCharacters(), функции, которая также обрабатывает экранирование всех запрещённых символов и последовательностей символов, writeEntityReference(), или последующие вызовы writeStartElement().
Класс XbelWriter из Примера закладок QXmlStream оборачивает QXmlStreamWriter. Его функция writeFile() иллюстрирует основные функции QXmlStreamWriter, упомянутые выше:
bool XbelWriter::writeFile(QIODevice *device)
{
xml.setDevice(device);
xml.writeStartDocument();
xml.writeDTD(QStringLiteral("<!DOCTYPE xbel>"));
xml.writeStartElement(QStringLiteral("xbel"));
xml.writeAttribute(XbelReader::versionAttribute(), QStringLiteral("1.0"));
for (int i = 0; i < treeWidget->topLevelItemCount(); ++i)
writeItem(treeWidget->topLevelItem(i));
xml.writeEndDocument();
return true;
}
© The Qt Company Ltd
Licensed under the GNU Free Documentation License, Version 1.3.
https://doc.qt.io/qt-5.13/xml-streaming.html