Logo
Startseite | PLUS Start | Shop | Mediadaten | Kontakt | Impressum | 4,548 Artikel Merker

XML mit PHP und Expat parsen


Anzeige

Mit der PHP-Erweiterung Expat lässt sich XML durch PHP parsen. Damit eröffnen sich neue Möglichkeiten. Denn XML ist als reine Datensprache 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 einzelner Daten aus XML-Dateien, sowie 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 XML-Daten zu handeln bietet Expat. Expat ist seit der PHP-Version 4 voll integriert und kann bei der Installation durch die Option "-with-xml" installiert werden.

Expat ist ereignisorientiert. Das bedeutet, dass zunächst einzelne Funktionen für verschiedene Ereignisse definiert werden. Ein Ereignis kann zum Beispiel sein: ein öffnendes Element, ein schließendes Element oder der Inhalt, der von einem öffnenden und einem schließendem Element eingeklammert ist.

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, die Arbeitsweise von Expat zu verstehen. Expat untersucht ein XML Dokument zeilenweise. Darum muss das Dokument mit einer Schleife Zeile für Zeile geparset werden.

Expat erkennt das öffnende Element, zum Beispiel <inhalt> und übergibt es an die definierte Funktion für öffnende Elemente. Daraufhin entdeckt er den Inhalt dazwischen. Ist dies einfacher Text, wird dieser an die Funktion überreicht, die diese Inhalte behandelt. Inhalte, die nicht weiter in andere Tags verschachtelt sind, nennt man CDATA - Character Data. Zum Abschluss 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, so dass 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.

      xml_set_default_handler($parser, "default");

Diese Funktion wird aufgerufen, wenn für das Ereignis keine andere Funktion definiert ist. Man kann sagen, dass die default-Funktion aufgerufen wird, wenn ein Fehler aufgetreten ist.

Der erste eigene Parser
Hier nun unser erster kleiner Parser, der auf das folgende XML-Dokument inhalt.xml zugeschnitten ist.

      <?xml version="1.0"?>
<inhalt>
Dies ist ein Platzhalter-Text.
</inhalt> 

Diese XML Datei wird von dem Parser in der Datei inhalt.php geparsed.

      <?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:

Inhalt
Dies ist ein Platzhalter-Text

Um die Arbeitsweise des Skriptes zu verstehen, betrachten wir jede Funktion einzeln. 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 können Attribute ü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 zugewiesen. Das heißt, die Variable ist nicht nur in der Funktion vorhanden, sondern auch außerhalb. So kann man direkt auf den Wert der Variablen zugreifen, ohne diesen an die Funktion zu übergeben. Zudem kann der Wert 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, 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 Elements 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, beziehungsweise 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 sorgt dafür, dass 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", das heißt 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.

Über Thiemo Fetzer

GravatarThiemo Fetzer lebt seit 2008 in London und promoviert dort im Fachbereich "Entwicklungsökonomie" an der London School of Economics. Zuvor hat er Wirtschaftswissenschaften, Mathematik und Informatik in Magdeburg und Ulm studiert. Website. Weitere Beiträge für Dr. Web: 30

Verwandte Artikel

Bookmarken! Diese Icons verlinken auf Bookmark Dienste bei denen Nutzer neue Inhalte finden und mit anderen teilen können.
  • MisterWong
  • del.icio.us
  • TwitThis
  • Hype
  • StumbleUpon
  • Facebook
  • Wikio DE
  • YahooMyWeb

2 Kommentare zu “XML mit PHP und Expat parsen”

  1. Wolle0rism schreibt am

    Soweit funzt ja alles, aber wie könnte ich jetzt die einzelnen elemente direkt ausgeben ohne allesamt hintereinander aufgereiht zu bekommen?

    [server]
    	[serverlogin]loginname[/serverlogin]
    	[name]Servername[/name]
    	[comment]Kommentar[/comment]
    	[gamemode]TimeAttack[/gamemode]
    	[laddermode]Normal[/laddermode]
    	[ladderlimitmin]0[/ladderlimitmin]
    	[ladderlimitmax]60000[/ladderlimitmax]
    	[type]TmForever[/type]
    	[version]2.11.16[/version]
    	[status]Running - Play[/status]
    	[coppers]891[/coppers]
    	[challengedownload]yes[/challengedownload]
    	[p2pupload]yes[/p2pupload]
    	[p2pdownload]yes[/p2pdownload]
    	[maxplayers]150[/maxplayers]
    	[maxspectators]5[/maxspectators]
    	[currentchallenge]Trackname[/currentchallenge]
    	[lastchallenge]Trackname[/lastchallenge]
    	[challengescount]64[/challengescount]
    	[playerscount]0[/playerscount]
    	[spectatorscount]0[/spectatorscount]
    [/server]
    
    (html klammern durch eckige ersetzt)

    Sorry das ich vielleicht eine etwas doofe Frage stelle, aber mir qualmt der Kopf und mein englisch is nich das beste um auf php.net alles zu verstehen >.<

    btw: warum kann ich mit dem "code" tag keinen code posten?

Trackbacks

  1. Was ist... Lexikon: SOAP | Lexikon, Webservices | Dr. Web Magazin

Meine Meinung

Bitte beachten Sie: Werbung und Spam sind unerwünscht und können eine Rechnung zur Folge haben. Woher kommen die Bilder neben den Kommentaren?