XML mit PHP und Expat parsen

XML mit PHP und Expat parsen XML ist das Datenformat der Zukunft. Mit der PHP Erweiterung Expat kann man XML durch PHP parsen. Dadurch eröffnen sich viele neue Möglichkeiten.

XML ist als reine Datensprache viel mächtiger als einfache SQL
basierende Datenbanken, die sich auf dem zweidimensionalen Rahmen
beschränken. Mit XML sind vielfach ineinander verschachtelte Datensysteme
möglich.



Die Erkennung der einzelnen Daten aus XML Dateien, und deren dynamische
Veränderung ist ungemein wichtig, da man ohne diese Funktionalität
nicht effektiv auf XML Datenbanken zurückgreifen kann.

Speziell für Webanwendungen ist es in dieser Hinsicht schwierig
mit XML umzugehen.

Eine einfache Möglichkeit mit XML Daten umzugehen bietet Expat.
Expat ist in die PHP 4 Version integriert, und kann bei der Installation
durch die Option “-with-xml” installiert werden.

Expat ist ereignisorientiert. Das bedeutet, das zunächst einzelne
Funktionen für die verschiedene Ereignisse definiert werden.

Ein Ereignis kann z.B. ein öffnendes Element, ein schließendes Element
oder der Inhalt, der von einem öffnenden, und einem schließendem
Element eingeklammert ist, sein.



Für folgende Elemente können Funktionen definiert werden.



  • Startendes Element, mit Attributen (<inhalt nr=”10″>)
  • Normaler Text “Character Data”, zwischen den öffnendem und schließendem
    Element
  • Abschließendes Element (</inhalt>)
  • Kommentare
  • DTD Anweisungen
  • Procession Instructions – eingebettete PHP Anweisungen


Wichtig ist, das man die Arbeitsweise von Expat versteht. Expat
untersucht ein XML Dokument zeilenweise. Aufgrund dessen muss das
Dokument Zeile für Zeile, also über eine Schleife von Expat geparset
werden.

Expat erkennt das öffnende Element, z.B. <inhalt>,
und übergibt es an die definierte Funktion für öffnende Elemente.
Darauf entdeckt er den Inhalt dazwischen. Ist dies einfacher Text,
dann wird dieser an die entsprechende Funktion überreicht, die die
Inhalte behandelt. Diese Inhalte, die nicht weiter in andere Tags
verschachtelt sind, nennt man CDATA, Character Data. Zum Schluss
wird das schließende Element gefunden, und entsprechend über die
definierte Funktion behandelt.


Einen XML Parser erzeugen

Ein XML Parser wird immer für das XML Dokument individuell erzeugt.



$parser = xml_parser_create();

Der Parser wird erzeugt. Die Variable $parser verweist auf den erzeugten
Parser, sodass dieser einmalig gekennzeichnet ist.



xml_set_element_handler($parser,”startElement”,”endElement”);

Hiermit werden die Funktionen für das öffnende, und das schließende
Element angegeben. “startElement” verweist auf die entsprechende
Funktion startElement(), und endElement verweist auf die entsprechende
Funktion “endElement”.



xml_set_character_data_handler($parser, “characterdata”);

Hiermit wird auf die Funktion für CDATA (normaler Text) verwiesen.



xml_set_processing_instruction_handler($parser, “pi”);


Hier wird auf die Funktion verwiesen, die Processing Instructions
behandelt (mehr dazu im zweiten Teil).



xml_set_default_handler($parser, “default”);


Diese Funktion wird aufgerufen, wenn für das Ereignis keine andere
Funktion definiert ist. Man kann sagen, das die default-Funktion
aufgerufen wird, wenn ein Fehler aufgetreten ist, z.B. wenn man
sich verschrieben hat usw.

Der erste eigene Parser

Die Arbeitsweise von Expat sollte nun im kleinen zumindest klar
sein. Hier nun unser erster kleiner Parser, der auf das folgende
XML Dokument zugeschnitten ist.

inhalt.xml


<?xml version=”1.0″?>

<inhalt>

Irgend ein Text, der nur dasteht, um

Platz zu verschwenden.

</inhalt>




Diese XML Datei wird von dem folgendem Parser geparsed.

inhalt.php

<?php

function startElement($parser, $element_name, $element_attribute)
{
global $ausgabe;
//Umwandeln in Kleinbuchstaben
$element_name = strtolower($element_name);
//Überprüfung des Elementnames
if ($element_name=="inhalt") {
$ausgabe .= "<h3>Inhalt</h3><p>";
}
}
function endElement($parser, $element_name) {
global $ausgabe;
// in Kleinbuchstaben umwandeln
$element_name = strtolower($element_name);
// Überprüfung des Names eines Elementes
if ($element_name=="inhalt") {
$ausgabe .= "</p>";
}
}
function cdata($parser, $element_inhalt) {
global $ausgabe;
// Der normale Text wird an $ausgabe angehängt
$ausgabe .= $element_inhalt;
}
$xmlFile = file("inhalt.xml");
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "cdata");

foreach($xmlFile as $elem)
{
xml_parse($parser, $elem);
}
xml_parser_free($parser);

echo $ausgabe;
?>

Die Ausgabe nach dem Aufruf des Skriptes sieht wie folgt aus:

Ihr erstes von PHP geparstes XML Dokument
Ihr erstes von PHP geparstes XML Dokument

Um die Arbeitsweise des Skriptes zu verstehen, sollte jede der definierten
Funktionen einzelne bearbeitet werden.

Zunächst behandeln wir die Funktion, die aufgerufen wird, wenn
Expat ein öffnendes Element findet. In unserem Beispiel ist
das <inhalt>.
An die Funktion wird die Variable $parser übergeben. In ihr
wird auf den erzeugten XML Parser verwiesen. Über die Variable
$element_name wird der Names des Elementes übergeben.
In unserem Beispiel ist der Name des Elementes "inhalt".
Zudem kann an die Funktion die Attribute, und deren Werte übergeben
werden. Wie Sie diese mit XML Parsen erfahren Sie im zweiten Teil
des Workshops.
In der ersten Zeile der Funktion selbst wird auf die Variable $ausgabe
verwiesen, und ihr Globale Eigenschaften gegeben. D.h. die
Variable ist nicht nur in der Funktion vorhanden, sondern auf außerhalb.
So kann man direkt auf den Wert der Variablen zugreifen, ohne diesen
an die Funktion zu übergeben. Zudem kann der Wert auf direkt
aus der Funktion heraus verändert werden.

function startElement($parser, $element_name, $element_attribute)
{
global $ausgabe;
//Umwandeln in Kleinbuchstaben
$element_name = strtolower($element_name);
//Überprüfung des Elementnames
if ($element_name=="inhalt") {
$ausgabe .= "<h3>Inhalt</h3><p>";
}
}

Die nächste Anweisung wandelt den Namen des Elementes
in Kleinbuchstaben um, da Expat die Namen eines Elementes immer
in Großbuchstaben übergibt. Dies muss nicht gemacht
werden, dient aber zu einem einfacheren Verständnis des Codes.
Im nächsten Teil wird überprüft, ob der Name des
Elementes "inhalt" ist. Ist dies der Fall, dann wird an
die Globale Variable $ausgabe der Inhalt "<h3>Inhalt</h3><p>"
über den Stringoperator "." angehängt.

Eigentlich ist eine Überprüfung auf den Namen des Elementes
nicht notwendig
, da in der XML Datei sowieso nur ein Element
vorkommt. Da wir jedoch in den nächsten Teil des Workshops
mit etwas komplexeren Beispielen in die Materie einsteigen, sollte
auf diese zwei Zeilen Code nicht verzichtet werden.

Nun, wollen wir uns mit der Funktion für den normalen Fließtext,
CDATA kümmern. Diese hat nur eine Aufgabe. Sie muss den Inhalt
des Elemenets an die Globale Variable $ausgabe anhängen.

function cdata($parser, $element_inhalt) {
global $ausgabe;
// Der normale Text wird an $ausgabe angehängt
$ausgabe .= $element_inhalt;
}

Der Inhalt des aktuell geparten Element wird über die Variable
$element_inhalt übergeben. Dieser wird an die Variable $ausgabe
angehängt.

Die letzte Funktion ist für die schließenden Elemente
zuständig. Diese Funktion arbeitet auf der gleichen Weise,
wie die Funktion für das öffnende Element.

function endElement($parser, $element_name) {
global $ausgabe;
// in Kleinbuchstaben umwandeln
$element_name = strtolower($element_name);
// Überprüfung des Names eines Elementes
if ($element_name=="inhalt") {
$ausgabe .= "</p>";
}
}

Das sind die Funktionen, die in diesem Beispiel benötigt werden.
Nun muss die XML Datei eingelesen werden, und daraufhin der Parser
definiert bzw. erzeugt werden.

$xmlFile = file("inhalt.xml");
$parser = xml_parser_create();
xml_set_element_handler($parser, "startElement", "endElement");
xml_set_character_data_handler($parser, "cdata");

foreach($xmlFile as $elem)
{
xml_parse($parser, $elem);
}
xml_parser_free($parser);

echo $ausgabe;

In der ersten Zeile wird die Datei über die file() Funktion
in ein Array gelesen. In der zweiten Zeile wird der Parser erzeugt.
Darauf werden die einzelnen Handler festgelegt.
Der letzte und wichtigste Teil des Skriptes ist, das der Inhalt
des Arrays über eine foreach-Schleife einzeln über die
Funktion xml_parse() geparsed wird.
In der vorletzten Zeile wird der Parser wieder "zerstört",
d.h. alle belegten Resourcen werden wieder frei gegeben. In der
letzten Zeile wird nun der Inhalt der Variablen $ausgabe ausgegeben.
In ihr befindet sich der Inhalt, der über die einzelnen Funktionen
"dynamisch" aus der XML Datei extrahiert wurde.
(tf)

This entry was posted in PHP. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *