Средства разработки 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