Philipp Hasenfratz: eigener XML-Parser; Speicheralgorithmus gesucht

Beitrag lesen

Hallihallo

ACHTUNG: Dies ist ein langes Posting (schreibwut); bitte erst ganz unten nachlesen, wo ___"endlich zur Frage"___ steht. Vielleicht will oder kann man nicht antworten; in dem Falle bringt auch der andere Text nix.

Einführung:

Seit gestern programmiere ich an einem eigenen XML-Parser (XML::DOM hat mir zwar sehr gut gefallen; aber meine Programme werden bei grossen XML-files einfach zu lange, weil man sich ja nur ziemlich schwerfällig durch die Struktur "browsen" kann). XPath wäre wohl die bessere Wahl, aber ich will mal wieder was eigenes basteln (ich hasse das Anwenden von Fertigprodukten).
Nun, der Parser (in Version 1.0 - d. h. er kann grad mal Start/End-Tags, Attribute und Werte einlesen; von Namespaces und Element-deklarationen keine Spur; aber wenn sich dann mal jemand (vielleicht ich selber) dafür interessiert, ist das Modul erweiterbar) ist nahezu fertig, ich hab nur noch Schwierigkeiten mit der Methode save, welche aus den Daten im RAM-Speicher den XML-stream erzeugt.

Wie wird das XML-Infoset intern verwaltet:
   Jeder Start-tag bekommt eine eindeutige pathID zugewiesen. In einem Hash (%pathes{$pathID}) stehen alle Daten zu einem solchen path (z. B. Name, Wert, Attribute, ...).
   XML-stream:
      <adressen>                        PathID : 1
         <adresse>                      PathID : 2
            <name>Hasenfratz</name>     PathID : 3
         </adresse>
         <adresse>                      PathID : 4
            <name>anderer Name</name>   PathID : 5
         </adresse>
      </adressen>

Die Daten des Pathes 5 sehen z. B. so aus:

$pathes{'5'} = {
   ChildOf => '4',  # Das <name>-Element ist Untermenge des Pathes 4
   NodeValue => 'anderer Name',
   NodeType  => 2,  # NodeType 2 : end-point, enthält also einen Wert
   NodeName  => 'name',
   Attributes => {...},
   ...
}

Nun geht es darum den XML-stream aus diesen Informationen wiederherzustellen:

Eine rekursive Lösung habe ich bereits erarbeitet, die ist auch nicht schwer:

sub _iterate
{
   my $self   = shift;
   my $pathID = shift;
   my $XMLstreamPtr = shift;
   $$XMLstreamPtr .= "<startTag>";
   my @subPathes = $self->getChilds($pathID);
   foreach (@subPathes)
   {
      $self->_iterate($_, $XMLstreamPtr);
   }
   $$XMLstreamPtr .= "<endTag>";
}

Nun, bei sehr grossen XML-files wird's wohl etwas kritisch mit dem Speicher (besonders, wenn viele XML-files auf dem Webserver geparsed werden müssen). Also möchte ich eine "lineare" Methode anwenden. Habe auch schon was gebastelt, aber ich bin irgendwie unfähig, dem Programm zu sagen, dass Tag's auch geschlossen werden sollen.

Endlich zur Frage:
Kann mir jemand ein (programmiertechnisch einfach zu implementierendes) Kriterium geben, wann, welcher und wieviele Tags geschlossen werden. Ich dachte etwa an folgendes, scheint aber nicht zu funktionieren:

while ( ... solange nach dem aktuellen path noch ein Element
        auf der gleichen "Ebene" kommt )
{
   schliesse den Tag und...
   $currentPathID = Das Vaterelement(parentPathID) vom $currentPathID
}

Sorry für das lange Posting

Philipp