nur den Anfang einer Datei einlesen
-
Hallo,
ich würde gerne einen Tipp haben, wie ihr folgendes Problem lösen würdet:Mein Programm kann verschiedene Typen von Informationstypen behandeln, die in einer XML-Datei liegen. Alle sind unterschiedlich aufgebaut
Bei einer Methode bekomme ich nur den Pfad zu einer solchen XML-Datei übergeben. Ich würde gerne dem Nutzer den Konfor geben, dass er nicht wählen muss, welcher Informationstyp ist.
Da die XML-Dateien von anderen Stellen kommen habe ich keinen Einfluss auf den Aufbau und kann nicht sagen, dass jeder als ersten Tag <Type>Typename</Typ> einbauen muss.
Aber ich weiß wie die XML-Dateien aufgebaut sind. Jetzt dachte ich mir, ich suche nach dem ersten Tag nach dem <?xml version=...?> und vergleiche diesen mit denen, die ich kenne und entscheide so, was es ist.
Damit dies auch bei sehr großen Dateien sehr schnell geht, will ich nicht alles einlesen, sondern nur einen Stream von vorne durchsuchenHabe mir das so vorgestellt (PseudoCode):
filestream = open File on filePath int startPosition = filestream.find(?>) + 1 //damit ist sichergestellt, dass es nach dem <? xml-Eintrag ?> ist - was aber wenn es den nicht gibt? std::string tagname = alles zwischen ersten "<" und ersten ">" ab Position startPositionDachte mir, so eine weiterführende Funktionalität könnte mir eine MFC-Klasse bieten, weshalb ich mir CStdioFile angeschaut habe. Leider hat diese nur ein eine read-Methode aber nicht ein "find".
Nun wollte ich hier fragen, ob ihr mit so etwas Erfahrung habt und mir Tipps geben könnt (habe es bewusst nicht in das MFC-Forum geschrieben, da mir egal ist mit was ich es umsetze).
Danke für eure Hilfe
-
Ich würde einen XML Parser dazu benutzen:
PugiXML
RapidXML
TinyXML
...Ev. sind einige ein wenig besser geeignet als andere, wegen der Performance.
Simon
Edit:
Wahrscheinlich wäre eine SAX implementierung für dich geeigneter.
-
hallo,
danke für die Antwort.anschließend wird ein xml-parser benutzt (altovaxml), wenn ich weiß welches format ich habe.
deshalb dachte ich mir, dass für das einlesen der ersten paar zeichen, bis ich weiß was es ist, ein normaler stream am besten geeignet ist
-
hm, hab grad über deine Idee weiterüberlegt.
AltovaXML baut auf Xerces auf, damit habe ich ja einen Parser den ich kurz für die Aufgabe auch hernehmen kann.
Wollte nur um den Parser rum, weil ich Bedenken habe, dass die Klasse das XML komplett einliest, was ja nicht nötig ist.
Aber wenn ein XML-Parser auch nur so weit liest, wie er für den Moment braucht, kommt es aufs gleiche raus
-
sorry dass ich grad spamme aber meine Gedanken kommen grad Stück für Stück

Hab nun bei Xerces in die API geschaut und dort steht, dass sie DOM, SAX, und SAX2 anbieten.
Kann mir wer erklären, was diese Funktionen unterscheidet? Wo die Vor- und Nachteile sind!?Danke
-
DOM: http://en.wikipedia.org/wiki/Document_Object_Model
SAX: http://en.wikipedia.org/wiki/Simple_API_for_XML
-
Kennt sich wer mit Xerces aus?
Komme da nicht weiter, lese seit Stunden rum.xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser(); //damit nicht alles eingelesen wird dachte ich mir, ich lese nur das erste xercesc::XMLPScanToken token; parser->parseFirst(_fileName, token); //nun will ich den Namen des ersten Elements haben, //was ja das Wurzelelement sein duerft //und genau das will ich, mehr brauch ich nichtWie ich an den Namen des Wurzelelements komme check ich nicht. Hab verschiedene Sachen über DOMDocument gemacht, hab geschaut ob ich das über GRammar bekomme...
ich habe das Gefühl, dass ich nur dumm rum probiere und in den Samples und API hab ich bis jetzt auch die Lösung noch nicht gefunden.Wenn sich wer auskennt und weiß was ich machen muss, fänd ich das toll
-
nur mit parser->parseFirst(_fileName, token); hab ichs nicht hinbekommen.
So komme ich grad auf das Ergebnis:
xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser(); parser->setValidationScheme(xercesc::XercesDOMParser::Val_Always); parser->setDoNamespaces(true); // optional xercesc::ErrorHandler* errHandler = (xercesc::ErrorHandler*) new xercesc::HandlerBase(); parser->setErrorHandler(errHandler); parser->parse(_fileName); xercesc::DOMDocument* document = parser->adoptDocument(); xercesc::DOMNode* firstNode = document->getFirstChild(); CString rootName = firstNode->getLocalName();So wird aber alles eingelesen, was ich nicht will.
Anstelle von parse(_fileName) kann ich aber auchxercesc::XMLPScanToken token; parser->parseFirst(_fileName, token); parser->parseNext(token);machen.
Wie geht es am geschicktesten und schnellsten (schnell auf Performance bezogen)? Hab nicht das Gefühl als wäre das der beste Weg.
Danke
-
Nimm einen SAX Parser - ich denke Xerces kann das.
Lies auf Wikipedia oder sonst wo nach warum genau SAX.