tinyxml - iterieren durch die xml
-
Ich hab eine Klasse XMLObject, die hauptsächlich das Laden und Speichern von XML als Objekthierarchie übernehmen soll. Mein Problem ist, dass nur das erste gefundene Element analysiert wird:
<?xml version=1.0> <elementa> <elementaa1> <elementaa1a>wert</elementaa1a> <elementaa1b>wert</elementaa1b> <elementaa1c>wert</elementaa1c> </elementaa1> <elementaa2> <elementaa2a>wert</elementaa2a> </elementaa2> </elementa>In diesem Falle wird nur elementaa1 mit allen unterelementen(!) abgehandelt..
hier mein Code:
void XMLObject::createDocument () { if (this->doc != NULL) delete doc; TiXmlDeclaration * decl = new TiXmlDeclaration( "1.0", "", "" ); this->doc = new TiXmlDocument(); doc->LinkEndChild(decl); doc->LinkEndChild(myNode); } int XMLObject::load (string filename) { this->createDocument(); doc->LoadFile(filename.c_str()); // file doesn't exist if (!doc->LoadFile()) { return -1; } doc->Print(); this->myNode = doc->FirstChild("adventure"); //string value = this->myNode->Value(); read (); return 0; } bool XMLObject::handleNode(TiXmlNode * pNode) { return false; return 0; } void XMLObject::read () { TiXmlNode *elem = this->myNode->FirstChild(); while(elem) { cout << "Pruefe element " << elem->Value() << endl; for (elem; elem; elem = elem->NextSibling()) if (! handleNode (elem)) { cout << elem->Value() << " als Variablen hinzugefuegt. " << endl; this->elements.push_back(elem); } } }das handleNode ist virtual, eine abgeleitete Klasse sieht so aus:
bool Adventure::handleNode(TiXmlNode *pNode) { string value = pNode->Value(); if (value == "switch") { // create switch this->addChild(XMLObject::ptr(new Switch(pNode))); return true; } else if (value == "item") { // create item this->addChild(XMLObject::ptr(new Item(pNode))); return true; } else if (value == "room") { // create room this->addChild(XMLObject::ptr(new Room(pNode))); return true; } return false; }Das print im load liefert mir die komplette hierarchie.
Beim Save wird wieder nur das erste Child abgearbeitet.
Kann mir wer erklären, was da jetzt hakt?
-
P.S.: Bitte entschuldigt die Kommentarfreiheit, aber ich bin grad auf ner Kiste beschäftigt, wo jedes Tippen ein Gräuel ist.. Ich wills erstmal am Laufen haben..
-
Ich verstehe das Problem noch nicht so ganz.
Ist dein Problem, dass zum Beispiel <elementaa1a> nicht behandelt wird? Falls ja, du läufst ja auch nur eine Ebene darüber durch das XML File. So tief gehst du ja nicht.
Rekursiv lässt es sich wunderbar lösen, bis in den letzten Winkel der XML Datei runterzulaufen.
Oder ist dein Problem etwa bei einem solchen XMl File
<?xml version="1.0" ?> <elementa> ... </elementa> <elementb> ... </elementb><elementb> nie behandelt wird? Wenn das der Fall ist: das ist kein gültiges XML File. Es darf nur ein erstes Element geben. Was tinyxml dann genau macht, weiß ich allerdings nicht.
-
nein, so wie es jetzt steht. elementaa1 wird abgearbeitet, elementaa2 nicht.
sorry, hatte mich etwas vertipptquasi tut das ding so, als ob dieses hier der einzige Inhalt der Datei wäre
<elementa> <elementaa1> <elementaa1a>wert</elementaa1a> <elementaa1b>wert</elementaa1b> <elementaa1c>wert</elementaa1c> </elementaa1> </elemanta>
-
Ah, ich glaub ich seh den Fehler:
void XMLObject::read () { TiXmlNode *elem = this->myNode->FirstChild(); while(elem) { cout << "Pruefe element " << elem->Value() << endl; for (elem; elem; elem = elem->NextSibling()) if (! handleNode (elem)) { cout << elem->Value() << " als Variablen hinzugefuegt. " << endl; this->elements.push_back(elem); } } }In der for()-Schleife läufst du durch die Elemente a,b,c durch (also die "ganz weit unten"). Du nutzt dafür TiXmlNode *elem. Nach dem Element c wird elem == NULL, und damit bricht auch die while()-Schleife ab.
Probiers mal so (ungetestet):
void XMLObject::read () { TiXmlNode *elem = this->myNode->FirstChild(); while(elem) { cout << "Pruefe element " << elem->Value() << endl; for (TiXmlNode* elem2 = elem; elem2; elem2 = elem2->NextSibling()) if (! handleNode (elem2)) { cout << elem2->Value() << " als Variablen hinzugefuegt. " << endl; this->elements.push_back(elem2); } elem = elem->NextSibling(); } }Schöner ist es eventuell mit 2 for()-Schleifen. Aber funktionieren sollte es eigentlich auch so.
-
hmm.. also mein Code ist eh scheinbar eine kaputte Version zwischen zwei Ständen.
So siehts jetzt aus:void XMLObject::read () { TiXmlNode *elem = this->myNode->FirstChild(); while(elem) { cout << "Pruefe element " << elem->Value() << endl; if (! handleNode (elem)) { cout << elem->Value() << " als Variablen hinzugefuegt. " << endl; this->elements.push_back(elem); } elem = elem->NextSibling(); } }Ich hab aber gerade etwas interessantes herausgefunden. Wenn ich das doc->Print() nach dem read() (load->Methode) starte, ist tatsächlich auch nur noch das im Dokument enthalten, was read ausliest.
Irgendwie gehen meine Daten im Nirvana verschütt, noch bevor ich sie handlen kann..Woran das liegt kann ich mir einfach nicht erklären. Werde mal weiter forschen.
Kennt jemand einen entsprechenden bug in TinyXML 2.3.4 (DevPack)
-
DocJunioR schrieb:
P.S.: Bitte entschuldigt die Kommentarfreiheit, aber ich bin grad auf ner Kiste beschäftigt, wo jedes Tippen ein Gräuel ist.. Ich wills erstmal am Laufen haben..
Was ist Kommentarfreiheit?
-
ich bat nur um entschuldigung dafür, dass mein Code unkommentiert, quasi Kommentarfrei ist. Und äeh,, ja. Ich rede immer so blödsinnig.
-
Zur Kommentarfreiheit würde ich sagen:
Wenn die variabeln und methoden namen gut gewählt sind, so sind keine Kommentare nötig.Es geht nicht drum kryptischen Code zu schreiben und dann im Kommentar den zu entschlüsseln. Es sollte so sein, dass der Code lesbar ist und die Idee aus dem Code hervor geht.
Das ist meine Meinung...
Simon
-
Das sehe ich etwas anders..
aber wie löst das jetzt mein Problem?