/XML - nur einen Teil eines Dokuments parsen
Andreas Lindig
- php
0 molily
guten Tag geneigtes Forum,
ich parse ein Dokument mit dem SAX-Parser Expat in PHP. Gut, jetzt will ich nur Elemente mit bestimmter ID einlesen, aber wie?
Beispiel:
<quotings>
<quote id="1">
<category id="c1 c2 c3"/>
...
</quote>
<quote id="2">
<category id="c4 c5"/>
...
</quote>
<quote id="3">
<category id="c3 c5 c6"/>
...
</quote>
</quotings>
jetzt will ich z.B. nur die Elemente 1 und 3 einlesen, weil sie die category "c3" enthalten, denn ich will alle Einträge mit der category "3" ausgeben, sonst nichts.
Jetzt soll ja der Vorteil eines SAX-Parsers gerade eben sein, daß man nicht das ganze (evtl. riesige) Dokument in den Speicher liest.
Wie geht man da praktisch vor? Ich rufe ja z.B. diese Funktion auf:
// Handler fuer Elemente ( oeffnende / schliessende Tags ) setzen
xml_set_element_handler( $parser, "start_element", "end_element" );
und 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. Jetzt müsste ich doch den Vorgang bis zum vorigen "</qutoe>" wieder rückgängig machen. 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.
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?
Gruß, Andreas
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):
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
Hallo Mathias,
ich parse ein Dokument mit dem SAX-Parser Expat in PHP.
Es gibt einfachere Möglichkeiten, sich Schmerzen zuzufügen.
hehe, welche schlägst Du vor - ich kenne mich mit S/M nicht so aus ;-)
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
NEIN! - ich will natürlich nicht. Aber es ist für die Zitatesammlung von SELFHTML und da muß ich mich wohl oder übel (eher letzteres ;-) an das hier gebräuchliche Format anpassen.
Was du vorhast, sieht nach einer typischen Datenbankabfrage aus.
find ich auch ;-) und in DB wäre es auch schon fertig.
vielen Dank für Deine Ausführungen. Der entscheidende Denkanzatz war, die Prüfungen im end-event-Handler durchzuführen. Es funktioniert jetzt. Daß das Dokument immer komplett geparst werden muß, war mir mangels XML-Kenntnissen nicht so klar. Aber sei's drum...
Gruß, Andreas