Autor podstrony: Krzysztof Zajączkowski

Stronę tą wyświetlono już: 3094 razy

XML (rozszerzony język znaczników) to format zapisu danych w formie tekstu, który jest bardzo często wykorzystywany do zapisu danych. Najbardziej znanym wykorzystaniem tego formatu jest HTML wykorzystywany przez strony internetowe do formatowania danych i wyglądu strony. XML jest także wykorzystywany przez wiele innych aplikacji takich jak np. Inkscape, który do zapisu danych i ich formatowania wykorzystuje w przebiegły sposób format XML. Z tego względu warto wiedzieć co nieco o tym formacie danych i możliwości jego wykorzystania.

Prosty przykład kodu XML

Rzućmy łaskawym okiem na taki oto prosty kawałek kodu:

<movies> <movie title="Red Dragon" year="2002"/> <movie title="Silence of the lambs" year="1991"/> </movies>

Dokumenty XML mają strukturę drzewiastą, co oznacza, że:

  • główny element root (korzeń) w dokumencie morze być tylko jeden, w przypadku powyższego kodu tym korzeniem jest znacznik movies;
  • korzeń morze mieć dowolną liczbę gałęzi, a gałęzie z kolei mogą również zawierać kolejne gałęzie. W przypadku powyższego kodu gałęzie to wszystkie znaczniki movie, które w tym przypadku nie zawierają ani treści ani podgałęzi więc zamknięte są znacznikiem />;

Warto też wiedzieć, że każda gałąź czy korzeń ma swoją nazwę oraz atrybuty. Nazwą korzenia dokumentu z powyższego kodu jest movies, korzeń ten nie ma atrybutów, natomiast atrybuty posiadają gałęzie o nazwie movie, nazwy atrybutów tychże gałęzi to:

  • title - zawiera tytuł filmu;
  • year - zawiera rok filmu

Można by rozszerzyć powyższy dokument np do takiej postaci:

<movies> <movie title="Red Dragon" year="2002"> <actors> <actor name="Anthony Hopkins" role="Dr Hannibal Lecter"/> <actor name="Edward Norton" role="Will Graham"/> </actors> </movie> <movie title="Silence of the lambs" year="1991"/> </movies>

W tym przypadku film "Red Dragon" ma gałąź actors (aktorzy) a ta zawiera kolejne gałęzie przechowujące informacje o aktorach i ich rolach.

Przykładowa implementacja odczytu, edycji i zapisu danych XML

Zróbmy sobie mały projekcik bazy danych filmów. Ograniczę się tutaj do minimalnej liczby elementów ponieważ chodzi mi jedynie o pokazanie jak w Qt można tworzyć, wczytywać i zapisywać dane XML. W tym celu konieczne będzie wykorzystanie następujących klas dostępnych w Qt:

  • QDomDocument - tworzy obiekt dokumentu XML;
  • QDomElement - element drzewa dokumentu;
  • QDomNode - węzeł drzewa dokumentu;
  • QDomNodeList - lista węzłów drzewa dokumentu

Klasa, która będzie zajmowała się obsługą bazy danych nazwana została przeze mnie MovieDatabase, a jej deklaracja w pliku moviesdatabase.h wygląda następująco:

#ifndef MOVIESDATABASE_H #define MOVIESDATABASE_H #include <QObject> #include <QFile> #include <QTextStream> #include <QtXml/QtXml> class MoviesDatabase : public QObject { Q_OBJECT QDomDocument document; QDomElement root; QString filePath; public: explicit MoviesDatabase(const QString &filePath, QObject *parent = 0); void addMovie(const QString &title, uint year); bool exists(const QString &title, uint year); void save(); void writeMovies(); signals: public slots: }; #endif // MOVIESDATABASE_H

W pliku moviesdatabase.cpp kod klasy:

#include "moviesdatabase.h" MoviesDatabase::MoviesDatabase(const QString &filePath, QObject *parent) : QObject(parent), filePath(filePath) { QFile fileOpenXML(filePath); bool allIsLoaded = false; if(fileOpenXML.open(QIODevice::ReadOnly | QIODevice::Text)){ qDebug() << "Database:" << filePath << "opened"; if(document.setContent(&fileOpenXML)){ qDebug() << "Database document readed correctly"; root = document.firstChildElement(); if(root.nodeName() == "movies"){ allIsLoaded = true; } } fileOpenXML.close(); } if(!allIsLoaded){ root = document.createElement("movies"); document.appendChild(root); } } void MoviesDatabase::save(){ QFile fileSaveXML(filePath); if(fileSaveXML.open(QIODevice::WriteOnly | QIODevice::Text)){ fileSaveXML.write(document.toString().toLatin1()); fileSaveXML.close(); } } bool MoviesDatabase::exists(const QString &title, uint year){ QDomNodeList movies = root.elementsByTagName("movie"); QDomElement movie; for(int index = 0; index < movies.count(); index++){ movie = movies.at(index).toElement(); if(movie.attribute("title") == title && movie.attribute("year").toUInt() == year){ return true; } } return false; } void MoviesDatabase::addMovie(const QString &title, uint year){ if(exists(title, year)){ qDebug() << "Film" << title << "z" << year << "roku juz jest w bazie danych"; return ; } QDomElement movie = document.createElement("movie"); movie.setAttribute("title", title); movie.setAttribute("year", year); root.appendChild(movie); } void MoviesDatabase::writeMovies(){ QDomNodeList movies = root.elementsByTagName("movie"); qDebug() << "========================================================================"; qDebug() << "Lista filmow w bazie danych"; qDebug() << "========================================================================"; QDomElement movieElement; for(int i = 0; i < movies.count(); i++){ movieElement = movies.at(i).toElement(); qDebug() << "Tytul:"; qDebug() << movieElement.attribute("title"); qDebug() << "Rok:"; qDebug() << movieElement.attribute("year").toUInt() << "n"; } }

I w końcu użycie tejże klasy w funkcji main:

#include <QCoreApplication> #include "moviesdatabase.h" int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); MoviesDatabase moviesdtb("database.xml"); moviesdtb.addMovie("Red Dragon", 2002); moviesdtb.addMovie("Silence of the lambs", 1991); moviesdtb.writeMovies(); moviesdtb.save(); return a.exec(); }

Wynik działania programu po dwukrotnym jego uruchomieniu powinien być następujący:

Database: "database.xml" opened
Database document readed correctly
Film "Red Dragon" z 2002 roku juz jest w bazie danych
Film "Silence of the lambs" z 1991 roku juz jest w bazie danych
========================================================================
Lista filmow w bazie danych
========================================================================
Tytul:
"Red Dragon"
Rok:
2002

Tytul:
"Silence of the lambs"
Rok:
1991
Strony powiązane
strony powiązane
  1. doc.qt.io/qt-4.8/qdomdocument.html - opis klasy QDomDocument na stronie dokumentacji Qt
  2. doc.qt.io/qt-4.8/qdomelement.html - opis klasy QDomElement na stronie dokumentacji Qt
  3. doc.qt.io/qt-4.8/qdomnode.html - opis klasy QDomNode na stronie dokumentacji Qt
Layout wykonany przez autora strony, wszelkie prawa zastrzeżone. Jakiekolwiek użycie części lub całości grafik znajdujących się na tej stronie bez pisemnej zgody jej autora surowo zabronione.