[C/C++] xmlparser

  • Hallo Gemeinde!


    Ich bastle gerade an einem XML-Parser, der mir eine XML Datei einliest.


    Am anfang habe ich mich mit libxml rumgeschlagen... das hat eigentlich auch funktioniert. Aber irgendwie ist das nicht ganz C++ Konform, weswegen ich dann auf libxml++ umgestiegen bin.


    Meine beiden Beispiele, habe ich beide über die Examples der beiden libs gebaut.


    Nur bei der libxml++ steig ich gerade nicht mehr durch.


    Hier der kl. Teil worum es geht:


    Ich habe eine Funktion parseNode die beim ersten Aufruf den Node und eine Zahl übergeben bekommt. Die Funktion ruft sich selbst wieder auf (rekursiv) bis sie alle Nodes durch hat.


    Bei der libxml ist das ganze eigentlich sehr ähnlich wie bei der libxml++, nur mit dem unterschied, dass ich bei der libxml nur bei einem child die funktion rekursiv aufrufe.


    Bei der libxml++ ist das irgendwie auch so, nur versteh ichs eben nicht.


    Hier mal das Beispiel mit der libxml


    Wenn ich die XML-Datei damit einlesen, schaut die Ausgabe so aus:


    Man sieht: Die erste Zahl zeigt mir sozusagen die Tiefe an, dann die zweite Zahl die Nummerierung in jedem einzelnen Menü und die dritte Zahl sollte eigentlich die Nummer des Menüs darstellen, nur hatte ich an der stelle dann auf die libxml++ umgeschwenkt (ist auch nicht wichtig, das würde ich ja noch hinbekommen)


    So jetzt kommen wir zum umbau zu libxml++. Hier schaut die Funktion dann so aus:


    (ich weiss, das könnte man noch schöner machen, aber zur Optimierung komme ich dann noch, wenns geht)
    So, und hier ist die Ausgabe dann folgende:



    Wie man hier sieht, funktioniert die Tiefenzählung (erste Zahl). Aber da sitzt genau mein verständnisproblem! Denn in diese Funktion wird !! pro eintrag !! aufgerufen. Was man auch schön an der zweiten Zahl sehen kann, denn diese ist immer 0.


    Kann mir jemand erklären, wie das funktioniert? Warum funktioniert die Zählung der Ebene (erste Zahl).


    Theoretisch ist es doch so, dass die Funktion beim aufruft hingeht und schaut ob sie eine der Zeilen zugeordnet werden kann und gibt entsprechend dann die Ausgabe aus.
    Als nächstes ruft diese sich dann so lange wieder auf, bis alles notes durch sind. Dabei sollte aber jeder aufruf (was einer Zeile ausgabe entspricht!) die übergebene Zahl hochzählen...


    also sollte die Ausgabe doch so aussehen!


    Aber tut sie nicht... Ich steig da gerade absolut nicht mehr druch...


    Wäre über einen Tip dankbar.


    Wer es mal selbst testen möchte, dem habe ich meinen src angehängt
    Die beiden Beispiele sind wie folgt zu kompilieren:

    Code
    g++ -g `xml2-config --cflags --libs` -o _xmlmenu _xmlmenu.cpp # meine erste version mit libxml
    gcc -g `pkg-config libxml++-2.6 --cflags --libs` -o xmlmenu xmlmenu.cpp # meine zweite version mit libxml++


    Gruß,
    Thomas

  • Hallo Thomas,


    beim ersten Aufruf der Funktion wird "Root" ausgegeben. Dann werden alle Kinder von "Root" rekursiv aufgerufen mit um eins erhöhtem Parent (also alle Kinder mit dem gleichen Wert für Parent). Im rekursiven Aufruf werden nun alle "SystemItem"s in der Schleife (oben) durchgegangen. MainMenuIndex wird erst nach der Schleife erhöht, also genau vor dem nächsten rekursiven Aufruf. Dadurch ist MainMenuIndex auf der nächten Ebene wieder 0 (da ja nicht statisch) und Parent um eines höher. Jetzt werden alle "PluginItem"s abgearbeitet - wieder ohne MainMenuIndex zu erhöhen. Und so weiter.


    Durch das Erhöhen von Parent im rekursiven Aufruf misst Du die Rekursionstiefe. So ein Verhalten wie Du es ganz unten erwartest, kannst Du so nicht erzeugen. Dazu brauchst Du eine statische Variable wie Du sie schon bei MenuNr verwendest.


    So ist zumindest mein Verständnis.


    Viele Grüße
    recorder

  • Zitat

    Original von recorder
    beim ersten Aufruf der Funktion wird "Root" ausgegeben. Dann werden alle Kinder von "Root" rekursiv aufgerufen mit um eins erhöhtem Parent (also alle Kinder mit dem gleichen Wert für Parent).


    ja, so schaut es auf jeden fall aus... aber wo ist die schleife dazu im zweiten Beispiel?


    Dass ist genau das was mir nicht in den Kopf will. Ich sehe nur die Schleife die auch den Rekursions-Parameter (Parent) erhöht.

  • Wenn Du in der Root-Ebene bist (Parent == 0), wird die Funktion in dieser Schleife für jedes Unterelement nochmal aufgerufen:

    Code
    for(Node::NodeList::iterator iter = list.begin(); iter != list.end(); ++iter)
    		{
    			parseNode(*iter, Parent+1); //recursive
    		}


    Da Parent == 0, wird für jede Kind-Node parseNode(*iter, 1) aufgerufen, wodurch in der ersten Ebene Parent immer 1 ist. Von dort aus, wo Parent == 1, wird jeweils parseNode(*iter, 2) aufgerufen. Die lokale Variable Parent ändert sich ja nicht.

  • ahhhh !!


    Jetzt versteh ichs! Danke! Hab wohl wirklich auf dem Schlau gestanden :schiel

Jetzt mitmachen!

Sie haben noch kein Benutzerkonto auf unserer Seite? Registrieren Sie sich kostenlos und nehmen Sie an unserer Community teil!