Средства разработки Qt включают в себя функционал по работе с XML файлами, который позволяет как создавать XML файлы, так и читать их, что может быть полезно для создания программ по автоматическому созданию XML разметок, конфигурационных файлов, использующих XML , либо для парсинга XML-файлов .
Для записи файлов в формате XML используется класс QXmlStreamWriter, тогда как для чтения XML файлов используется другой класс QXmlStreamReader.
Программный код был написан в QtCreator 3.3.1 на основе Qt 5.4.1.
Структура проекта для работы с XML файлом
В данном проекте используется минимум файлов:
- XMLExample.pro - профайл;
- mainwindow.h - заголовочный файл основного окна приложения;
- mainwindow.cpp - исходный код окна;
- main.cpp - основной исходный файл, с которого стартует приложение;
- mainwindow.ui - формочка основного окна приложения;
mainwindow.ui
На этот раз в формочку главного окна необходимо добавить достаточно большое количество элементов, чтобы оно стало выглядеть следующим образом:
Главное окно приложения для работы с XML файлом Список всех элементов, с которыми будет производиться работа в программном коде:
- checkBox - первый чекбокс;
- checkBox_1 - второй чекбокс;
- checkBox_2 - третий чекбокс;
- lineEditCB1 - lineEdit для первого чекбокса;
- lineEditCB2 - lineEdit для второго чекбокса;
- lineEditCB3 - lineEdit для третьего чекбокса;
- lineEditRead - lineEdit, в котором указывается путь к файлу для чтения;
- lineEditWrite - lineEdit, в котором указывается путь к файлу для записи;
- dialogReadButton - кнопка для вызова диалога сохранения файла, в данном случае выполняется просто выбор файла, с которым будет производиться работа;
- dialogButton - кнопка для вызова диалога записи файла, в данном случае выполняется просто выбор файла, с которым также будет производиться работа;
- readButton - кнопка выполнения чтения из файла;
- generateButton - кнопка для выполнения записи в файл.
mainwindow.h
В заголовочном файле подключаются библиотеки для работы с QXmlStreamWriter и QXmlStreamReader. Также объявляются слоты обработчиков нажатий кнопок.
- #ifndef MAINWINDOW_H
- #define MAINWINDOW_H
- #include <QMainWindow>
- #include <QFileDialog>
- #include <QXmlStreamWriter>
- #include <QXmlStreamReader>
- #include <QXmlStreamAttribute>
- #include <QMessageBox>
- #include <QFile>
- namespace Ui {
- class MainWindow;
- }
- class MainWindow : public QMainWindow
- {
- Q_OBJECT
- public:
- explicit MainWindow(QWidget *parent = 0);
- ~MainWindow();
- private slots:
- /* Слоты обработчиков кнопок, работающих с записью в файл */
- void on_generateButton_clicked();
- void on_dialogButton_clicked();
- /* Слоты обработчиков кнопок, работающих с чтением из файла */
- void on_readButton_clicked();
- void on_dialogReadButton_clicked();
- private:
- Ui::MainWindow *ui;
- };
- #endif // MAINWINDOW_H
mainwindow.cpp
В данном исходном файле осуществляется чтение и запись данных в XML-файл, а также подстановка параметров из XML-файла в форм главного окна.
- #include "mainwindow.h"
- #include "ui_mainwindow.h"
- MainWindow::MainWindow(QWidget *parent) :
- QMainWindow(parent),
- ui(new Ui::MainWindow)
- {
- ui->setupUi(this);
- }
- MainWindow::~MainWindow()
- {
- delete ui;
- }
- /* Метод, выполняющий запись информации в XML-файл
- * */
- void MainWindow::on_generateButton_clicked()
- {
- /* Открываем файл для Записи с помощью пути, указанного в lineEditWrite */
- QFile file(ui->lineEditWrite->text());
- file.open(QIODevice::WriteOnly);
- /* Создаем объект, с помощью которого осуществляется запись в файл */
- QXmlStreamWriter xmlWriter(&file);
- xmlWriter.setAutoFormatting(true); // Устанавливаем автоформатирование текста
- xmlWriter.writeStartDocument(); // Запускаем запись в документ
- xmlWriter.writeStartElement("resources"); // Записываем первый элемент с его именем
- xmlWriter.writeStartElement("checkBox_1"); // Записываем тег с именем для первого чекбокса
- /* На основе состояния чекбокса записываем атрибут "boolean"
- * с указанием состояния чекбокса в этом атрибуте
- * */
- xmlWriter.writeAttribute("boolean",
- (ui->checkBox->isChecked() ? "true" : "false"));
- /* Записываем также в тело этого элемента строку из соответствующего lineEdit
- * */
- xmlWriter.writeCharacters(ui->lineEditCB1->text());
- xmlWriter.writeEndElement(); // Закрываем тег
- /* Повторяем те же действия для двух других чекбоксов
- * */
- xmlWriter.writeStartElement("checkBox_2");
- xmlWriter.writeAttribute("boolean",
- (ui->checkBox_2->isChecked() ? "true" : "false"));
- xmlWriter.writeCharacters(ui->lineEditCB2->text());
- xmlWriter.writeEndElement();
- xmlWriter.writeStartElement("checkBox_3");
- xmlWriter.writeAttribute("boolean",
- (ui->checkBox_3->isChecked() ? "true" : "false"));
- xmlWriter.writeCharacters(ui->lineEditCB3->text());
- xmlWriter.writeEndElement();
- /* Закрываем тег "resources"
- * */
- xmlWriter.writeEndElement();
- /* Завершаем запись в документ
- * */
- xmlWriter.writeEndDocument();
- file.close(); // Закрываем файл
- }
- /* Метод, вызывающий диалоговое окно выбора файла для сохранения данных
- * */
- void MainWindow::on_dialogButton_clicked()
- {
- /* Вызываем диалог выбора файла для сохранения */
- QString filename = QFileDialog::getSaveFileName(this,
- tr("Save Xml"), ".",
- tr("Xml files (*.xml)"));
- /* Устанавливаем в lineEditWrite путь к файлу, с которым будем работать */
- if(filename != ""){
- ui->lineEditWrite->setText(filename);
- }
- }
- void MainWindow::on_readButton_clicked()
- {
- /* Открываем файл для Чтения с помощью пути, указанного в lineEditWrite */
- QFile file(ui->lineEditRead->text());
- if (!file.open(QFile::ReadOnly | QFile::Text))
- {
- QMessageBox::warning(this,
- "Ошибка файла",
- "Не удалось открыть файл",
- QMessageBox::Ok);
- } else {
- /* Создаем объект, с помощью которого осуществляется чтение из файла */
- QXmlStreamReader xmlReader;
- xmlReader.setDevice(&file);
- xmlReader.readNext(); // Переходит к первому элементу в файле
- /* Крутимся в цикле до тех пор, пока не достигнем конца документа
- * */
- while(!xmlReader.atEnd())
- {
- /* Проверяем, является ли элемент началом тега
- * */
- if(xmlReader.isStartElement())
- {
- /* Проверяем, относится ли тег к одному из чекбоксов.
- * Если "ДА", то выполняем проверку атрибута чекбокса
- * и записи для lineEdit
- * */
- if(xmlReader.name() == "checkBox_1")
- {
- /* Забираем все атрибуты тега и перебираем их для проверки на соответствие
- * нужному нам атрибуту
- * */
- foreach(const QXmlStreamAttribute &attr, xmlReader.attributes()) {
- /* Если найден нужный атрибут, то по его значению устанавливаем
- * состояние чекбокса
- * */
- if (attr.name().toString() == "boolean") {
- QString attribute_value = attr.value().toString();
- ui->checkBox->setChecked((QString::compare(attribute_value , "true") == 0) ? true : false);
- }
- }
- /* забираем текст из тела тега и вставляем его соответствующий lineEdit
- * */
- ui->lineEditCB1->setText(xmlReader.readElementText());
- /* аналогично работаем с остальными тегами */
- } else if (xmlReader.name() == "checkBox_2"){
- foreach(const QXmlStreamAttribute &attr, xmlReader.attributes()) {
- if (attr.name().toString() == "boolean") {
- QString attribute_value = attr.value().toString();
- ui->checkBox_2->setChecked((QString::compare(attribute_value , "true") == 0) ? true : false);
- }
- }
- ui->lineEditCB2->setText(xmlReader.readElementText());
- } else if (xmlReader.name() == "checkBox_3"){
- foreach(const QXmlStreamAttribute &attr, xmlReader.attributes()) {
- if (attr.name().toString() == "boolean") {
- QString attribute_value = attr.value().toString();
- ui->checkBox_3->setChecked((QString::compare(attribute_value , "true") == 0) ? true : false);
- }
- }
- ui->lineEditCB3->setText(xmlReader.readElementText());
- }
- }
- xmlReader.readNext(); // Переходим к следующему элементу файла
- }
- file.close(); // Закрываем файл
- /* В данном коде не осуществляется проверка на закрытие тега
- * поскольку в этом нет необходимости, но функционал QXmlStreamReader это позволяет
- * */
- }
- }
- /* Метод, вызывающий диалоговое окно выбора файла для чтения данных
- * */
- void MainWindow::on_dialogReadButton_clicked()
- {
- /* Вызываем диалог выбора файла для чтения */
- QString filename = QFileDialog::getOpenFileName(this,
- tr("Open Xml"), ".",
- tr("Xml files (*.xml)"));
- /* Устанавливаем в lineEditRead путь к файлу, с которым будем работать */
- if(filename != ""){
- ui->lineEditRead->setText(filename);
- }
- }
В результате мы получаем возможность создать XML-файл с параметрами чекбоксов и наших объектов типа lineEdit , а также распарсить этот файл и установить полученные данные в соответствующие чекбоксы и объекты lineEdit.
Полученный файл должен будет выглядеть следующим образом:
- <?xml version="1.0" encoding="UTF-8"?>
- <resources>
- <checkBox_1 boolean="false">XML</checkBox_1>
- <checkBox_2 boolean="false">Example</checkBox_2>
- <checkBox_3 boolean="true">EVILEG</checkBox_3>
- </resources>
Итог
В результате должно получиться приложение, которое создаёт или перезаписывает XML-файл , забирая данные из чекбоксов и соответствующих полей lineEdit , а также производящее парсинг этого XML-файла с установкой данных в чекбоксы и поля lineEdit .
Приложение для работы с XML файлами
Не могли бы предоставить пример, где больше уровней в xml файле?
Это конечно можно, но насколько больше? И применительно к какому виду... Всё упирается же в то, куда именно будет этот XML применяться.
Например, чтение данных из XML можно сделать и с помощью QDomDocument. А если учесть, что SVG файл также фактически является XML документом, то Вы можете посмотреть следующий пример, для ознакомления с вытягиванием данных из XML файла:
SvgReader на Qt. Восстановление данных из файла SVG в QGraphicsScene