Seite 1 von 1
Navigation durch xml Dokumente
Verfasst: 8. Dezember 2010 00:41
von surfhai
Hallo,
ich weiß es kann trivial klingen, aber ich komm einfach nicht klar. Ich hab ein xml Dokument aus einer OpenOffice Spreadsheet Datei (content.xml) aus dem ich Werte auslesen will.
Da dacht ich mir les ich es mit einem QDomDocument ein. Hab mich hier
http://zez.org/article/articleview/28/1/ etwas über die Struktur informiert aber blick nicht ganz durch wie ich das ganze Durchlaufen soll.
hier mal meine ersten versuche damit klar zu kommen:
Code: Alles auswählen
QDomDocument
Utils::readODS(QString filepath)
{
QuaZipFile zipfile;
zipfile.setZipName(filepath);
zipfile.setFileName(QString("content.xml"));
QDomDocument xml;
xml.setContent(&zipfile);
QStringList searchlist;
searchlist << "office:document-content"
<< "office:body"
<< "office:spreadsheet";
QDomNodeList n(xml.childNodes());
for(int i = 0; i < searchlist.count(); ++i)
{
int j;
for(j = 0; j < n.count(); ++j)
{
if(n.at(j).nodeName() == searchlist.at(i))
{
break;
}
if(j == (n.count() - 1))
{
return QDomDocument();
}
}
xml = n.at(j);
n = xml.childNodes();
}
return xml;
Aber das funktioniert im moment noch nicht und wird je weiter unten man ist auch immer "fälscher". Kann mir vielleicht jemand ein klares Konzept zeigen wie ich am besten xml Dokumente durchlaufen kann?
Die Funktion soll mir nur die relevante Daten Sektion aus dem xml Dokument zurückgeben, die ich dann mit anderen Funktionen weiter durchsuchen will.
Gruß Thorsten
Verfasst: 8. Dezember 2010 06:33
von Christian81
Wenn man kein DOM braucht dann empfiehlt sich
http://doc.trolltech.com/4.7/qxmlstreamreader.html . Dort ist auch ein Beispiel zu finden.
Verfasst: 8. Dezember 2010 10:12
von RHBaum
Kann mir vielleicht jemand ein klares Konzept zeigen wie ich am besten xml Dokumente durchlaufen kann?
Das XML ne hirarische Struktur hat, hasst ja sicher mitbekommen
Die Frage ist,
WONACH genau suchst Du. Und daraus leitet sich das
WIE ab.
Beispiel: In 99,9999999% Aller Faelle weisst du, oder musst Du, die genaue Position in der Hirarchie kennen. Das Heisst Du hasst die Info, dass dein gesuchtes Element z.b. im Dokument unter NodeEbene1_A->NodeEbene2_C->NodeEbene3_B ... zu finden ist.
Dementsprechend Laesst du dir das Dokument geben (was gleichzeitig nen Node ist) , dort holst Dir das SubElement NodeEbene1_A. Von dem holst Dir NodeEbene2_C von dem NodeEbene3_B usw. bis halt dein element hasst.
Schluesselfunktion ist hier QDomNode::firstChildElement
in 0,00000001% der Faelle weisst nicht, wo in der Hirarchie liegt was suchst, sondern weisst nur das das ding nen eindeutigen Namen hat.
Dann isst es wie wenn Du nen komplettes directory nach einer Datei durchsuchst. Eventuell rekursiver ansatz !
Ciao ...
Verfasst: 8. Dezember 2010 14:21
von surfhai
ok, das ist Praktisch... ich glaub mit QXmlStreamReader komm ich eher klar als mit QDomDocument.
Aber ich möchte dennoch verstehn wie man das auch mit QDomDocument bewältigt. Mein Code is doch nich so ganz falsch, er sollte das 99% Beispiel sein. Das einzige was nicht funktioniert ist die Zuweisung des gefundenen Teilstücks des Dokuments um darin eine Ebene weiter zu suchen.
Dieses Stück code funktioniert nicht wie es soll
Wenn das ausgeführt wird ist die Variable xml quasi leer. Auch wenn ich das hier Probiere:
Das heißt also das ich das so nicht machen kann. Könnte das jemand zum laufen bringen? Die herangehensweise ist wahrscheinlich hier schon falsch und wie ich die Klassen einsetze.
Verfasst: 8. Dezember 2010 15:50
von RHBaum
Warum QDomDocument als Rueckgabewert ?
Nen DOMDocument repraesentiert nen komplettes XML dokument, inclusive allen versions und formatierungs-infos etc.
Du willst aber nur nen "Teilstücks des Dokuments" zurueckgeben ... und kein komplett ausformuliertes XML-Dokument.
QDomNode - wenn ne Position in der Hirarchie brauchst
QDomElement - wenn sicher bist das es ein Elementeintrag ist und du die Attribute zu brauchst.
QDomElement ist eine spezialisierung von QDOMNode !
Ciao ...
Verfasst: 8. Dezember 2010 16:25
von upsala
Und alternativ kann man auch QXmlQuery benutzen, wenn man sich mit XQuery bzw. XPath auskennt.
Verfasst: 9. Dezember 2010 16:31
von surfhai
Hab das ganze jetzt mal mit QXmlStreamReader versucht. Das Programm stürzt aber komischerweise ab und ich hab keine Ahnung warum.
project.pro
Code: Alles auswählen
QT += core gui xml
TARGET = project
TEMPLATE = app
DEPENDPATH += . quazip
INCLUDEPATH += . quazip
SOURCES += main.cpp\
thread.cpp \
utils.cpp
HEADERS += thread.h \
utils.h
include(quazip/quazip.pri)
main.cpp
Code: Alles auswählen
#include <QtGui/QApplication>
#include "utils.h"
#include "thread.h"
#include <QString>
#include <QDebug>
#include <QXmlStreamReader>
int main(int argc, char *argv[])
{
QXmlStreamReader * xml = new QXmlStreamReader();
xml = Utils::readODS(QString("threads.ods"));
Thread * x = new Thread(xml, QString("metrisch"));
return 0;
}
}
thread.h
Code: Alles auswählen
#ifndef THREAD_H
#define THREAD_H
#include <QObject>
#include <QString>
#include <QXmlStreamReader>
class Thread : public QObject
{
Q_OBJECT
public:
explicit Thread(QXmlStreamReader * xml, QString threadType, QObject *parent = 0);
explicit Thread(const Thread &, QObject *parent = 0);
signals:
public slots:
private:
double dataP;
double dataD;
QString type;
qint64 startLineNumber;
QXmlStreamReader * xml;
};
#endif // THREAD_H
thread.cpp
Code: Alles auswählen
#include "thread.h"
#include <QXmlStreamReader>
#include <QDebug>
Thread::Thread(QXmlStreamReader * xml, QString threadType, QObject *parent) :
QObject(parent)
{
type = threadType;
while(!xml->atEnd())
{
xml->readNext();
if(xml->name().toString() == "table" &&
xml->isStartElement() &&
xml->attributes().value("name").toString() == type)
{
startLineNumber = xml->lineNumber();
qDebug() << type;
}
}
if (xml->hasError())
{
qDebug() << "Error" << xml->error()
<< xml->errorString();
qDebug() << "at line number " << xml->lineNumber();
qDebug() << "at column number " << xml->columnNumber();
qDebug() << "at character offset " << xml->characterOffset();
}
}
Thread::Thread(const Thread& t, QObject *parent):
QObject(parent)
{
type = t.type;
xml = t.xml;
dataP = t.dataP;
dataD = t.dataD;
}
utils.h
Code: Alles auswählen
#ifndef READODS_H
#define READODS_H
#include <QString>
#include <QXmlStreamReader>
#include <quazip.h>
#include <quazipfile.h>
class Utils
{
public:
Utils();
static QXmlStreamReader * readODS(QString filepath);
};
#endif // READODS_H
utils.cpp
Code: Alles auswählen
#include "utils.h"
#include <QString>
#include <QDebug>
#include <QXmlStreamReader>
#include <QXmlStreamAttributes>
#include <quazip.h>
#include <quazipfile.h>
Utils::Utils()
{
}
QXmlStreamReader *
Utils::readODS(QString filepath)
{
QuaZipFile zipfile;
zipfile.setZipName(filepath);
zipfile.setFileName(QString("content.xml"));
zipfile.open(QIODevice::ReadOnly);
QXmlStreamReader * xml = new QXmlStreamReader(&zipfile);
return xml;
}
compiler output
Code: Alles auswählen
Führe Build-Schritte für Projekt project aus...
Unveränderte Konfiguration, qmake-Schritt wird übersprungen.
Starte "/usr/bin/make" -w
make: Entering directory `/home/tg/Dokumente/Entwicklung/C++/project-build-desktop'
g++ -c -m64 -pipe -g -Wall -W -D_REENTRANT -DQT_XML_LIB -DQT_GUI_LIB -DQT_CORE_LIB -DQT_SHARED -I/usr/share/qt/mkspecs/linux-g++-64 -I../project -I/usr/include/QtCore -I/usr/include/QtGui -I/usr/include/QtXml -I/usr/include -I../project -I../project/quazip -I. -I. -I. -o thread.o ../project/thread.cpp
g++ -m64 -Wl,--hash-style=gnu -Wl,--as-needed -o project main.o thread.o utils.o ioapi.o JlCompress.o quaadler32.o quacrc32.o quazip.o quazipfile.o quazipnewinfo.o unzip.o zip.o moc_thread.o moc_quazipfile.o -L/usr/lib -lQtXml -lQtGui -lQtCore -lpthread
make: Leaving directory `/home/tg/Dokumente/Entwicklung/C++/project-build-desktop'
Der Prozess "/usr/bin/make" wurde normal beendet.
Ausgabe
Code: Alles auswählen
Starte /home/tg/Dokumente/Entwicklung/C++/project-build-desktop/project...
Das Programm ist abgestürzt.
/home/tg/Dokumente/Entwicklung/C++/project-build-desktop/project beendet, Rückgabewert 0
Backtrace
Code: Alles auswählen
Thread 1 (Thread 0x7ffff7fab760 (LWP 14412)):
#0 0x00007fffffffe7b5 in ?? ()
#1 0x00007ffff6db37e6 in QIODevice::read(char*, long long) () from /usr/lib/libQtCore.so.4
#2 0x00007ffff6e60cc3 in ?? () from /usr/lib/libQtCore.so.4
#3 0x00007ffff6e61148 in ?? () from /usr/lib/libQtCore.so.4
#4 0x00007ffff6e6136e in ?? () from /usr/lib/libQtCore.so.4
#5 0x00007ffff6e6feff in QXmlStreamReader::readNext() () from /usr/lib/libQtCore.so.4
#6 0x00000000004065f7 in Thread::Thread (this=0x61cf30, xml=0x61e590, threadType=..., parent=0x0) at ../project/thread.cpp:20
#7 0x0000000000405e48 in main (argc=1, argv=0x7fffffffe078) at ../project/main.cpp:22
Verfasst: 9. Dezember 2010 16:53
von Christian81
Und mal wieder mangelhafte C Grundkenntnisse - heute schon der zweite Beitrag ...

Wie lange lebt zipfile ?
Verfasst: 9. Dezember 2010 19:51
von surfhai
Gut das du bei dem Fehler nicht erblindet bist

Ist mir nicht aufgefallen, dass zipfile so lang überleben muss. Wenn das so ist kann ich die Klasse Utils gleich ganz wegfallen lassen.
Danke für den Hinweis, ich hätte mich zu tode gesucht.