Anwendung: verwirrender Fehler bei XML - Datei
-
Hallo!
Zuerst schonmal:
Ja, ich habe die FAQ gelesen, und die Borland Hilfe und TROTZDEM hänge ich seit 2 Tagen über dem Problem:
Ich möchte einige Einstellungen aus meinem Programm in eine XML Datei speichern. Diese wird bei Bedarf, wenn sie noch nicht existiert, erstellt.
Klappt auch alles.
Dann übergebe ich meiner XML-Funktion einen String, z.b.: "Hallo\\das\\ist\\ein\\test". In der XML Datei soll dann dies stehen:<Hallo> <das> <ist> .... <Eintrag1>1</Eintrag1> <Eintrag2>1</Eintrag2> <Eintrag3>1</Eintrag3> .... </ist> </das> </Hallo>Das macht er auch...ABER..
wenn ich nun Werte einfügen will, dann Schreibt er die Einträge hintereinander, nicht untereinander (d.h. er schreibt kein newline in die XML Datei).<Hallo> <das> <ist> .... <Eintrag1>1</Eintrag1><Eintrag2>1</Eintrag2><Eintrag3>1</Eintrag3> .... </ist> </das> </Hallo>Das heißt ja im Prinzip, dass irgendwo im Code ein Fehler ist.
Hier der Copy-Paste Code zum selber Probieren:Ich würde mich über eine Rückmeldung freuen!
XML.cpp:
#include <vcl.h> #include <string> #pragma hdrstop #include "XML.hpp" using namespace std; //--------------------------------------------------------------------------- // XML - Datei speichern / anlegen //--------------------------------------------------------------------------- bool SaveXMLOption(string FileName, string XMLString, string ChildContent) { int count=GetXMLNote(XMLString,0).count; _di_IXMLNode tempKnoten1,tempKnoten2; NoteInfoStrukt tempNoteInfo =GetXMLNote(XMLString,1); if(XMLString=="") // XMLString darf nicht leer sein return false; if(FileExists(FileName.c_str())) { try { _di_IXMLDocument XMLDocument = LoadXMLDocument(FileName.c_str()); XMLDocument->Active = true; tempKnoten1 = XMLDocument->DocumentElement; for(int i=2;i<count;i++) { if(i%2) { if(tempKnoten2->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,i)).Node.c_str())==NULL) tempKnoten1 = tempKnoten2->AddChild(tempNoteInfo.Node.c_str()); else tempKnoten1 = tempKnoten2->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,i)).Node.c_str()); } else { if(tempKnoten1->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,i)).Node.c_str())==NULL) tempKnoten2 = tempKnoten1->AddChild((tempNoteInfo =GetXMLNote(XMLString,i)).Node.c_str()); else tempKnoten2 = tempKnoten1->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,i)).Node.c_str()); } } if(count%2) if(tempKnoten2->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,count)).Node.c_str())!=NULL) tempKnoten2->ChildNodes->Delete((tempNoteInfo = GetXMLNote(XMLString,count)).Node.c_str()); else if(tempKnoten1->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,count)).Node.c_str())!=NULL) tempKnoten1->ChildNodes->Delete((tempNoteInfo = GetXMLNote(XMLString,count)).Node.c_str()); _di_IXMLNode Node = XMLDocument->CreateElement((tempNoteInfo =GetXMLNote(XMLString,count)).Node.c_str(), L""); Node->NodeValue = WideString(ChildContent.c_str()); if(count%2) tempKnoten2->ChildNodes->Add(Node); else tempKnoten1->ChildNodes->Add(Node); // XML Dokument in eine Datei abspeichern XMLDocument->FileName=FileName.c_str(); XMLDocument->SaveToFile(XMLDocument->FileName); } catch (...){ return false; } return true; } else { try { TXMLDocument *XMLDocument = new TXMLDocument(""); // WICHTIG: kein Datei Namen übergeben, sonst Exception XMLDocument->Options = XMLDocument->Options << doNodeAutoIndent; // für die richtige Formatierung XMLDocument->Active = true; XMLDocument->Encoding = "UTF-16"; // Encoding festlegen, damit auch z.B. Umlauten richtig rüberkommen XMLDocument->FileName=FileName.c_str(); tempKnoten1 = XMLDocument->CreateElement((tempNoteInfo =GetXMLNote(XMLString,1)).Node.c_str(), ""); XMLDocument->DocumentElement = tempKnoten1; for(int i=2;i<count;i++) { if(i%2) if(tempKnoten2->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,i)).Node.c_str())==NULL) tempKnoten1 = tempKnoten2->AddChild(tempNoteInfo.Node.c_str()); else tempKnoten1 = tempKnoten2->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,i)).Node.c_str()); else if(tempKnoten1->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,i)).Node.c_str())==NULL) tempKnoten2 = tempKnoten1->AddChild((tempNoteInfo =GetXMLNote(XMLString,i)).Node.c_str()); else tempKnoten2 = tempKnoten1->ChildNodes->FindNode((tempNoteInfo = GetXMLNote(XMLString,i)).Node.c_str()); } _di_IXMLNode Node = XMLDocument->CreateElement((tempNoteInfo =GetXMLNote(XMLString,count)).Node.c_str(), L""); Node->NodeValue = WideString(ChildContent.c_str()); if(count%2) tempKnoten2->ChildNodes->Add(Node); else tempKnoten1->ChildNodes->Add(Node); // XML Dokument in eine Datei abspeichern XMLDocument->SaveToFile(); } catch (...) { return false; } return true; } } //--------------------------------------------------------------------------- //--------------------------------------------------------------------------- // XML - Knoten rausfiltern //--------------------------------------------------------------------------- NoteInfoStrukt GetXMLNote(string XMLString, int index) { NoteInfoStrukt myNoteInfo; int tempIndex=0; int count=0; string tempString=XMLString; myNoteInfo.Node=""; while((tempIndex=tempString.find("\\"))>=0) { if(count==0) count++; count++; tempString=tempString.substr(tempIndex+1); } tempString = XMLString; if((index<=count)&&(index>0)) { for(int i=0; i<index;i++) { if(index<count) myNoteInfo.Node=tempString.substr(0,tempString.find("\\")); else myNoteInfo.Node=tempString; tempString=tempString.substr(tempString.find("\\")+1); } } myNoteInfo.count=count; // Gesamtanzahl an Argumente zurückgeben return myNoteInfo; }XML.hpp:
#ifndef XMLH #define XMLH //--------------------------------------------------------------------------- // // XML - Header Datei // // Funktionen: // // bool SaveProfileOption(string , string , string ) // // //--------------------------------------------------------------------------- // #include <Classes.hpp> #include <Controls.hpp> #include <StdCtrls.hpp> #include <Forms.hpp> #include <ExtCtrls.hpp> #include "CSPIN.h" #include <Graphics.hpp> #include <oxmldom.hpp> #include <XMLDoc.hpp> #include <xmldom.hpp> #include <XMLIntf.hpp> #include <string> // //--------------------------------------------------------------------------- using namespace std; struct NoteInfoStrukt { int count; string Node; }; bool SaveXMLOption(string FileName, string XMLString, string ChildContent); NoteInfoStrukt GetXMLNote(string XMLString, int index); #endifUnit123.cpp:
#include "XML.hpp" ..... SaveXMLOption("profile.xml","Haupt\\Unterpunkt\\Menu\\Schritt1", "Test1"); SaveXMLOption("profile.xml","Haupt\\Unterpunkt\\Menu\\Schritt2", "Test2"); SaveXMLOption("profile.xml","Haupt\\Unterpunkt\\Menu\\Schritt3", "Test3");
-
Was mir jetzt spontan auffällt, ist, dass die Zeile
XMLDocument->Options = XMLDocument->Options << doNodeAutoIndent; // für die richtige Formatierungnur dann ausgeführt wird, wenn die Datei neu angelegt wird.
Vielleicht solltest Du Dir auch mal überlegen, den Code etwas übersichtlicher zu gestalten und zu kommentieren.
Von der Vorgehensweise her würde ich erstmal dafür sorgen eine gültige XMLDocument-Instanz zu haben, d.h. entweder eine bestehende Datei laden oder
eine neue Instanz erstellen.
Dann würde ich alles darauf loslassen, anstatt per Copy'n'Paste den Code doppelt reinzuklatschen. Diese "Programmiermethode" sorgt meines Erachtens
für schlecht lesbaren und vor allem schlecht wartbaren Code (alle Änderungen müssen doppelt eingepflegt werden). Wenn meine obige Vermutung stimmt,
wäre das schon der Beweis
Gruß,
Alexander
-
....shame on me

Hallo!
Danke für die Antwort und natürlich hast du recht.
Es lag an der einen Zeile, die du zitiert hattest.
Und natürlich mache ich mich mal ans Aufräumen des Codes.Einen schönen Tag noch!
-
So, die Zusammenlegung ist soweit abgeschlossen.
Jedoch bekomme ich jetzt immer eine Exception bei der Ausführung, wenn die XML-Datei schon vorhanden ist:
_di_IXMLNode tempKnoten1,tempKnoten2; TXMLDocument *XMLDocument=new TXMLDocument(""); // WICHTIG: kein Datei Namen übergeben, sonst Exception XMLDocument->FileName=FileName.c_str(); XMLDocument->Options = XMLDocument->Options << doNodeAutoIndent; // für die richtige Formatierung XMLDocument->LoadFromFile(); XMLDocument->Active = true; if(XMLDocument->IsEmptyDoc()) // Gibt es die XML - Datei schon? { // nein, dann neu erstellen XMLDocument->Encoding = "UTF-16"; // Encoding festlegen, damit auch z.B. Umlauten richtig rüberkommen tempKnoten1 = XMLDocument->CreateElement((tempNoteInfo =GetXMLNote(XMLString,1)).Node.c_str(), ""); XMLDocument->DocumentElement = tempKnoten1; } else // Ja, dann den root - Knoten erhalten tempKnoten1 = XMLDocument->DocumentElement; // <-- Hier die ExceptionEr kann irgendwie nicht den root-Knoten "XMLDocument->DocumentElement" erhalten.
Jedoch ist die XML - Datei fehlerfrei, denn Aktive ist auch auf "true" und "IsEmptyDoc" auch false.Weiß jemand weiter?
Hier zum nachvollziehen der Inhalt der XML-Datei
<?xml version="1.0" encoding="UTF-16"?> <PROFILES> <TEST> <Wizzard> <Step1>Test1</Step1> </Wizzard> </TEST> </PROFILES>