molily: /XML - nur einen Teil eines Dokuments parsen

Beitrag lesen

Hallo,

ich parse ein Dokument mit dem SAX-Parser Expat in PHP.

Es gibt einfachere Möglichkeiten, sich Schmerzen zuzufügen.

Jetzt soll ja der Vorteil eines SAX-Parsers gerade eben sein, daß man nicht das ganze (evtl. riesige) Dokument in den Speicher liest.

(Standardfrage: Willst du wirklich deine Daten in einem XML-Dokument speichert und kein richtiges Datenbanksystem verwenden? Was du vorhast, sieht nach einer typischen Datenbankabfrage aus.)

frühestens in der aufgerufenen Funktion "start_element" kann ich feststellen, ob ich im Element "category" bin und ob dieses im Attribut "id" den Wert "c3" stehen hat. Bis hierhin ist aber das Oberelement "quote" schon eingelesen worden.

»Bis dahin« meines Wissens nicht. Wenn der End-Tag-Event des category-Elements gefeuert wird, steht der Parser exakt an dieser Stelle und hat danach noch nichts eingelesen.

Jetzt müsste ich doch den Vorgang bis zum vorigen "</qutoe>" wieder rückgängig machen.

Welchen Vorgang? Die Verarbeitung könnte so ablaufen (angenommen, category ist nicht immer das erste Element des quote-Elements):

  • Wenn ein Start-Tag-Event mit dem Tagnamen quote gefeuert wird, speichere die ID in einem temporären Array A im globalen Scope.
  • Wenn ein Start-Tag-Event mit dem Tagnamen category gefeuert wird, im Handler prüfen, ob »c3« im id-Attribut steht. Falls ja, setze den globalen Flag F.
  • Die Verarbeitung der anderen Elemente nach dem quote-Start-Tag hängt davon ab, ob sie CDATA-Inhalt haben. In dem Fall speichere den Tagnamen beim Start-Tag-Event und eventuelle Attribute in einer temporären Variable im globalen Scope, dasselbe bei einem darauffolgenden CDATA-Event. Beim End-Tag-Event werden diese Daten in den Array A übertragen.
  • Wenn en End-Tag-Event mit dem Tagnamen quote gefeuert wird, prüfe, ob der Flag F gesetzt ist. Falls ja, hänge den Array an einen Array B im globalen Scope an.

Oder ich lese das ganze Element komplett ein und lösche es wieder, wenn es nicht die richtige id enthält. Aber ist das denn nicht perfomancelastig? Da wird ja schon wieder das ganze Dokument geparst.

Das ganze Element wird sowieso »eingelesen«. Der Unterschied zum DOM ist, dass zu keiner Zeit mehr als der aktuelle Token sowie wahrscheinlich der unmittelbare Kontext auf der Markupebene im Speicher liegt. Also die Daten, die die Event-Handler bekommen.
Das ganze Dokument wird sowieso geparst. Das heißt, du kannst das Parsen zwar vorzeitig abbrechen, aber logischerweise nicht verhindern, dass der Parser über Stellen im Dokument wandert, die für dich uninteressant sind, wenn danach noch Relevantes kommt.

Ach ja: wenn ich z.B. 10 Elemente mit der id "c3" eingelesen habe, soll auch Schluß sein mit lustig - auch wenn das Dokument z.B. 1000 Datensätze hat. Wie stoppe ich denn den Parservorgang?

Dann setze eine globale Variable, die zählt, wieviele Datensätze schon eingelesen wurden. Und führe xml_parse() immer mit kleinen Markuphäppchen aus, bis das Ende des Strings erreicht ist oder X gesuchte Datensätze eingelesen wurden.

Mathias