Webdesign mit CSS, XHTML und Javascript
Stil mit {stil}
Apr 2009
XML in PHP 5
PHP unterstützt XML schon in älteren Versionen. In PHP 4 kam die domxml-Erweiterung hinzu, etwas später die XSLT-Erweiterung. Allerdings sind die domxml- und XSLT-Erweiterungen dort niemals über eine experimentelle Phase hinausgekommen und waren auch nie per Vorgabe aktiviert. Zudem basierte die domxml-Erweiterung nicht auf dem DOM-Standard des W3C. PHP 5 hat darum XML völlig neu implementiert und sich an die Standards gehalten. Ab PHP 5 basieren alle XML-Erweiterungen auf der libxml2-Library des GNOME-Projekts.
Neben den neu implementieren domxml- und XSLT-Erweiterungen ist die SimpleXML-Erweiterung hinzugekommen und alle drei Erweiterungen sind in PHP 5 per Vorgabe aktiv.
PHP DOM
Das DOM (Document Object Model) ist der Standard für den Zugriff auf den XML-Baum. Die Namensgebung, Methoden und Parameter sind in PHP 5 jetzt dieselben wie z.B. in Javascript.
<?xml version="1.0" encoding="utf-8" ?>
<root>
<event>
<enum>101</enum>
<title>Digitale Fotografie für Einsteiger</title>
</event>
<event>
<enum>102</enum>
<title>Adobe Photoshop</title>
</event>
</root>
XML-Dateien laden und speichern
Die XML-Datei wird geladen, um daraus ein DomDocument-Object zu erzeugen:
$dom = new DomDocument();
$dom->load("events.xml");
Das XML-Dokument im Browser ausgeben:
print $dom->saveXML();
Als neue Datei speichern (sendet die Dateigröße an stdout):
print $dom->save("vorlesungen.xml");
Alle title-Element mit getElementsByTagname($tagname) ausgeben:
$titles = $dom->getElementsByTagName("title");
foreach($titles as $node) {
print $node->textContent . " ";
}
Die Eigenschaft textContent gehört nicht zum Standard des W3C, sondern bildet einfach nur einen intuitiven Zugriff auf die Textknoten eines Elements. Die passende Eigenschaft des W3C wäre:
$node->firstChild->data;
(allerdings nur, wenn sicher gestellt ist, dass firstChild der gewünschte Textknoten ist – ansonsten muss der Textknoten in einer Schleife durch alle Kindknoten gesucht werden).
DOM getElementsByTagName()
getElementsByTagName() gibt eine DomNodeList zurück, die durch eine Iteration mit foreach durchsucht werden kann. Einen direkten Zugriff auf die Knoten gibt $titles->item(0) – das gibt das erste title-Element zurück.
Eine andere Technik, die alle title-Elemente sammelt, wäre die Iteration über die Knoten – beginnend mit dem root-Element. Das ist zwar komplizierter, aber wenn mehr als ein title-Element gebraucht wird, am Ende doch flexibler:
foreach ($dom->documentElement->childNodes as $articles) {
// Wenn der Knoten ein Element (nodeType == 1) und der Name "item" ist, weiter laufen
if ($articles->nodeType == 1 && $articles->nodeName == "item") {
foreach ($articles->childNodes as $item) {
//wenn der Knoten ein Element mit dem Namen "title" ist, dann ausgeben
if ($item->nodeType == 1 && $item->nodeName == "title") {
print $item->textContent . " ";
}
}
}
}
XPath
XPath ist ein wenig wie SQL für XML und formuliert Abfragen (querys) nach Daten des XML-Objekts. Einen Knoten mit einem id-Attribut suchen:
$query = '//root/events[name = "'.$id.'"]'; $entries = $xp->query($query);
Mit XPath können wir ein XML-Dokument nach einem bestimmten Knoten nach bestimmten Kriterien durchsuchen. Um alle title-Knoten mit XPath zu lesen:
<?
$xp = new domxpath($dom);
$titles = $xp->query("/root/event/title");
foreach ($titles as $node) {
print $node->textContent . " ";
}
?>
Das ist zwar fast derselbe Code wie mit getElementsByTagName(), aber XPath ist viel mächtiger. Wenn ein title-Element als Kind des root-Elements vorläge (statt als Kind eines event-Elements), würde es von getElementsByTagname() zurückgegeben. /root/event/title hingegen greift nur auf das title-Element zu, das auf dem gewünschten Level platziert ist. Weitere Features sind:
/root/event[position()=1]/titlegibt dastitle-Element des erstenevent-Elements zurück./root/event/title[@id='foo']gibt alletitle-Elemente mit id="foo" zurück.- /root//title gibt alle
title-Elemente unterhalb vonarticleszurück. - Einen Knoten löschen:
$entries = $xp->query(".//root[@name = 'enum']");
$entries->enum(0)->parentNode->removeChild($entries->enum(0));
Wir können alle Elemente abfragen, die ein bestimmtes sibling-Element haben, die einen bestimmten Text enthalten oder Namensräume benutzen.
DOM manipulieren und schreiben
Mit dem Document Object Model können XML-Dateien nicht nur gelesen, sondern auch manipuliert und neu geschrieben werden. Ein neues Element in events.xml einfügen:
$event = $dom->getElementsByTagName("event");
$i = 0;
foreach ($event as $node) {
$i = $i + 1;
$ort = $dom->createElement("ort");
$orttext = $dom->createTextNode("Seminarraum " . $i);
$ort->appendChild($orttext);
$node->appendChild($ort);
}
print $dom->saveXML();
Der Code erzeugt ein Element ort und einen Textknoten mit dem text für ort. Der Textknoten wird an das ort-Element gehangen und das ort-Element an das event-Element.
SimpleXML
SimpleXML ist die jüngste Erweiterung der XML-Funktionen in PHP und macht einen besonders einfachen Zugriff auf XML-Dokumente möglich, bietet aber nur wenige Methoden. Alle title-Knoten als SimpleXML-Objekt lesen:
$sxml = simplexml_load_file("events.xml");
foreach($sxml->item as $item) {
print $item->title ." ";
}
Der Code lädt events.xml in ein SimpleXML-Objekt und holt dann alle item-Elemente mit der Eigenschaft $sxml->item. $item->title gibt den Inhalt des title-Elements zurück. Auch Abfragen sind mit assoziativen Arrays möglich: $item->title['id'].
Auch eine XPath-Schnittstelle existiert in SimpleXML und macht den Zugriff auf individuelle Knoten noch leichter:
foreach($sxml->xpath('/event/title') as $item) {
print $item . " ";
}
Der Code ist zwar nicht kürzer, aber in komplexen und tief verschachtelten XML-Dokumenten erspart XPath mit SimpleXML viel Tipparbeit.
XML-Dokumente mit SimpleXML manipulieren und schreiben
Mit SimpleXML können XML-Dokumente nicht nur gelesen, sondern bis zu einem gewissen Grad auch geändert werden.
$sxml->event->title = "Vorlesung Medientechnik"; // neuer Textinhalt des title-Knotens $sxml->event->title['id'] = 'foo'; // Attribut des title-Elements ändern $xmlString = $sxml->asXML(); // gibt das SimpleXML-Objekt als seriellen XML String zurück print $xmlString;
Umschalten zwischen DOM und SimpleXML
SimpleXML-Objekte lassen sich effizient in DomDocument-Objekte und zurück verwandeln:
$sxml = simplexml_import_dom($dom);$dom = dom_import_simplexml($sxml);
PHP Streams
Streams wurden in PHP 4.3 eingeführt und in PHP 5 verbessert. Sie stellen einen allgemeinen Datei- bzw. Netzwerkzugriff dar. PHP-Streams lesen und schreiben Daten von oder in so ziemlich jede erdenkliche Form von Speicher als würde hier auf eine Datei zugegriffen. Ein PHP-Stream kann z.B. eine Webseite oder eine Mailbox mit fopen() öffnen und in kleinen Häppchen lesen und schreiben, so dass die Anwendung nicht viel Speicher braucht und mehr simultane Anfragen parallel abhandeln kann. In PHP 5 wird ein PHP-Stream z.B. durch <xsl:include> oder die <xi:xinclude> Direktive eingebunden.
Links
- SimpleXML: http://www.php.net/simplexml/
- Streams: http://www.php.net/manual/en/ref.stream.php
Standards
- DOM: http://www.w3.org/DOM
- XSLT: http://www.w3.org/TR/xslt
- XPath: http://www.w3.org/TR/xpath
- XML Schema: http://www.w3.org/XML/Schema
- RelaxNG: http://relaxng.org/
- Xinclude: http://www.w3.org/TR/xinclude/

