Засоби розробки 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