Es gibt viele Techniken zum Lesen und Schreiben von XML mit PHP. Dieser Artikel stellt drei Methoden zum Lesen von XML vor: die Verwendung einer DOM-Bibliothek, die Verwendung eines SAX-Parsers und die Verwendung regulärer Ausdrücke. Das Schreiben von XML mithilfe von DOM- und PHP-Textvorlagen wird ebenfalls behandelt.
Das Lesen und Schreiben der Extensible Markup Language (XML) in PHP kann ein wenig beängstigend wirken. Tatsächlich können XML und alle damit verbundenen Technologien beängstigend sein, aber das Lesen und Schreiben von XML in PHP muss keine beängstigende Aufgabe sein. Zunächst müssen Sie ein wenig über XML lernen – was es ist und was Sie damit machen können. Dann müssen Sie lernen, wie man XML in PHP liest und schreibt, und es gibt viele Möglichkeiten, dies zu tun.
Dieser Artikel bietet eine kurze Einführung in XML und erklärt anschließend, wie man XML mit PHP liest und schreibt.
Was ist XML?
XML ist ein Datenspeicherformat. Es definiert weder, welche Daten gespeichert werden, noch definiert es das Format der Daten. XML definiert einfach Tags und die Attribute dieser Tags. Ein wohlgeformtes XML-Markup sieht folgendermaßen aus:
<Name>Jack Herrington</Name>
Dieses <name>-Tag enthält Text: Jack Herrington.
XML-Markup ohne Text sieht so aus:
<powerUp/>
Es gibt mehr als eine Möglichkeit, etwas in XML zu schreiben. Dieses Tag erzeugt beispielsweise die gleiche Ausgabe wie das vorherige Tag:
<powerUp></powerUp>
Sie können XML-Tags auch Attribute hinzufügen. Dieses <name>-Tag enthält beispielsweise die Attribute „first“ und „last“:
<Name zuerst="Jack" letzter="Herrington" />
Auch Sonderzeichen können in XML kodiert werden. Das &-Symbol kann beispielsweise wie folgt kodiert werden:
&
Eine XML-Datei mit Tags und Attributen ist wohlgeformt, wenn sie wie im Beispiel formatiert ist, was bedeutet, dass die Tags symmetrisch sind und die Zeichen korrekt codiert sind. Listing 1 ist ein Beispiel für wohlgeformtes XML.
Listing 1. Beispiel für eine XML-Buchliste
<Bücher>
<Buch>
<Autor>Jack Herrington</Autor>
<title>PHP Hacks</title>
<publisher>O'Reilly</publisher>
</Buch>
<Buch>
<Autor>Jack Herrington</Autor>
<Titel>Podcasting-Hacks</Titel>
<publisher>O'Reilly</publisher>
</Buch>
</Bücher>
|
Das XML in Listing 1 enthält eine Liste von Büchern. Das übergeordnete <books>-Tag enthält eine Reihe von <book>-Tags, von denen jedes die Tags <author>, <title> und <publisher> enthält.
Ein XML-Dokument ist korrekt, wenn seine Markup-Struktur und sein Inhalt durch eine externe Schemadatei überprüft werden. Schemadateien können in verschiedenen Formaten angegeben werden. Für diesen Artikel wird lediglich wohlgeformtes XML benötigt.
Wenn Sie glauben, dass XML der Hypertext Markup Language (HTML) sehr ähnelt, haben Sie Recht. XML und HTML sind beide Markup-basierte Sprachen und weisen viele Ähnlichkeiten auf. Es ist jedoch wichtig darauf hinzuweisen, dass ein XML-Dokument zwar wohlgeformtes HTML sein kann, aber nicht alle HTML-Dokumente wohlgeformtes XML sind. Das Newline-Tag (br) ist ein gutes Beispiel für den Unterschied zwischen XML und HTML. Dieses Newline-Tag ist wohlgeformtes HTML, aber kein wohlgeformtes XML:
<p>Dies ist ein Absatz<br>
Mit einem Zeilenumbruch</p>
Dieses Newline-Tag ist wohlgeformtes XML und HTML:
<p>Dies ist ein Absatz<br />
Mit einem Zeilenumbruch</p>
Wenn Sie HTML als wohlgeformtes XML schreiben möchten, folgen Sie dem Extensible Hypertext Markup Language (XHTML)-Standard des W3C-Komitees (siehe Ressourcen ). Alle modernen Browser können XHTML rendern. Darüber hinaus können Sie XML-Tools verwenden, um XHTML zu lesen und die Daten im Dokument zu finden, was viel einfacher ist als das Parsen von HTML.
Lesen Sie XML mithilfe der DOM-Bibliothek
Der einfachste Weg, wohlgeformte XML-Dateien zu lesen, ist die Verwendung der Document Object Model (DOM)-Bibliothek, die in einigen PHP-Installationen kompiliert ist. Die DOM-Bibliothek liest das gesamte XML-Dokument in den Speicher und stellt es als Knotenbaum dar, wie in Abbildung 1 dargestellt.
Abbildung 1. XML-DOM-Baum für Buch-XML
Der Bücherknoten oben im Baum verfügt über zwei untergeordnete Bücher-Tags. In jedem Buch gibt es mehrere Knoten: Autor, Herausgeber und Titel. Die Knoten „Autor“, „Herausgeber“ und „Titel“ verfügen jeweils über untergeordnete Textknoten, die Text enthalten.
Der Code, der die Buch-XML-Datei liest und den Inhalt mithilfe des DOM anzeigt, ist in Listing 2 dargestellt.
Listing 2. Buch-XML mit DOM lesen
<?php
$doc = new DOMDocument();
$doc->load( 'books.xml' );
$books = $doc->getElementsByTagName( "book" );
foreach( $books as $book )
{
$authors = $book->getElementsByTagName( "author" );
$author = $authors->item(0)->nodeValue;
$publishers = $book->getElementsByTagName( "publisher" );
$publisher = $publishers->item(0)->nodeValue;
$titles = $book->getElementsByTagName( "title" );
$title = $titles->item(0)->nodeValue;
echo „$title – $author – $publishern“;
}
?>
|
Das Skript erstellt zunächst ein neues DOMdocument-Objekt und lädt das Buch-XML mithilfe der Load-Methode in dieses Objekt. Anschließend verwendet das Skript die Methode getElementsByName, um eine Liste aller Elemente unter dem angegebenen Namen abzurufen.
In der Schleife des Buchknotens verwendet das Skript die Methode getElementsByName, um den nodeValue der Autoren-, Herausgeber- und Titel-Tags abzurufen. nodeValue ist der Text im Knoten. Das Skript zeigt diese Werte dann an.
Sie können PHP-Skripte wie folgt auf der Befehlszeile ausführen:
%phpe1.php
PHP-Hacks – Jack Herrington – O'Reilly
Podcasting-Hacks – Jack Herrington – O'Reilly
%
Wie Sie sehen, gibt jeder Buchblock eine Zeile aus. Das ist ein guter Anfang. Was aber, wenn Sie keinen Zugriff auf die XML-DOM-Bibliothek haben?
Lesen Sie XML mit dem SAX-Parser
Eine andere Möglichkeit, XML zu lesen, ist die Verwendung eines XML Simple API (SAX)-Parsers. Die meisten PHP-Installationen enthalten einen SAX-Parser. Der SAX-Parser läuft auf einem Callback-Modell. Jedes Mal, wenn ein Tag geöffnet oder geschlossen wird oder wenn der Parser Text sieht, wird die benutzerdefinierte Funktion mit Informationen über den Knoten oder Text zurückgerufen.
Der Vorteil des SAX-Parsers besteht darin, dass er wirklich leichtgewichtig ist. Der Parser speichert Inhalte nicht über längere Zeiträume im Speicher und kann daher für sehr große Dateien verwendet werden. Der Nachteil besteht darin, dass das Schreiben von SAX-Parser-Rückrufen sehr umständlich ist. Listing 3 zeigt Code, der SAX verwendet, um eine Buch-XML-Datei zu lesen und den Inhalt anzuzeigen.
Listing 3. Buch-XML mit SAX-Parser lesen
<?php
$g_books = array();
$g_elem = null;
Funktion startElement( $parser, $name, $attrs )
{
global $g_books, $g_elem;
if ( $name == 'BOOK' ) $g_books []= array();
$g_elem = $name;
}
Funktion endElement( $parser, $name )
{
global $g_elem;
$g_elem = null;
}
Funktion textData( $parser, $text )
{
global $g_books, $g_elem;
if ( $g_elem == 'AUTHOR' ||
$g_elem == 'PUBLISHER' ||
$g_elem == 'TITEL' )
{
$g_books[ count( $g_books ) - 1 ][ $g_elem ] = $text;
}
}
$parser = xml_parser_create();
xml_set_element_handler( $parser, "startElement", "endElement" );
xml_set_character_data_handler( $parser, "textData" );
$f = fopen( 'books.xml', 'r' );
while( $data = fread( $f, 4096 ) )
{
xml_parse( $parser, $data );
}
xml_parser_free( $parser );
foreach( $g_books as $book )
{
echo $book['TITLE']." - ".$book['AUTHOR']." - ";
echo $book['PUBLISHER']."n";
}
?>
|
Das Skript richtet zunächst das Array g_books ein, das alle Bücher und Buchinformationen im Speicher enthält, und die Variable g_elem enthält den Namen des Tags, das das Skript gerade verarbeitet. Das Skript definiert dann die Callback-Funktion. In diesem Beispiel sind die Rückruffunktionen startElement, endElement und textData. Rufen Sie beim Öffnen und Schließen der Markierung die Funktionen startElement und endElement auf. TextData wird für den Text zwischen dem öffnenden und schließenden Tag aufgerufen.
In diesem Beispiel sucht das startElement-Tag nach dem book-Tag, um ein neues Element im book-Array zu beginnen. Die Funktion textData prüft dann das aktuelle Element, um festzustellen, ob es sich um ein Herausgeber-, Titel- oder Autoren-Tag handelt. Wenn ja, fügt die Funktion den aktuellen Text in das aktuelle Buch ein.
Damit das Parsen fortgesetzt werden kann, erstellt das Skript mithilfe der Funktion xml_parser_create einen Parser. Legen Sie dann das Rückruf-Handle fest. Anschließend liest das Skript die Datei und sendet Teile der Datei an den Parser. Nachdem die Datei gelesen wurde, entfernt die Funktion xml_parser_free den Parser. Am Ende des Skripts wird der Inhalt des g_books-Arrays ausgegeben.
Wie Sie sehen, ist dies viel schwieriger, als dieselbe Funktionalität in das DOM zu schreiben. Was ist, wenn es keine DOM-Bibliothek und keine SAX-Bibliothek gibt? Gibt es Alternativen?
Analysieren Sie XML mit regulären Ausdrücken
Ich bin mir sicher, dass einige Ingenieure mich dafür kritisieren werden, dass ich diese Methode überhaupt erwähnt habe, aber es ist möglich, XML mit regulären Ausdrücken zu analysieren. Listing 4 zeigt ein Beispiel für die Verwendung der preg_-Funktion zum Lesen einer Buchdatei.
Listing 4. XML mit regulären Ausdrücken lesen
<?php
$xml = "";
$f = fopen( 'books.xml', 'r' );
while( $data = fread( $f, 4096 ) ) { $xml .= $data }
fclose( $f );
preg_match_all( "/<book>(.*?)</book>/s",
$xml, $bookblocks );
foreach( $bookblocks[1] als $block )
{
preg_match_all( "/<author>(.*?)</author>/",
$block, $author );
preg_match_all( "/<title>(.*?)</title>/",
$block, $title );
preg_match_all( "/<publisher>(.*?)</publisher>/",
$block, $publisher );
echo( $title[1][0]." - ".$author[1][0]." - ".
$publisher[1][0]."n" );
}
?>
|
Beachten Sie, wie kurz dieser Code ist. Zunächst wird die Datei in einen großen String eingelesen. Verwenden Sie dann eine Regex-Funktion, um jedes Buchelement zu lesen. Verwenden Sie abschließend eine foreach-Schleife, um jeden Buchblock zu durchlaufen und den Autor, den Titel und den Herausgeber zu extrahieren.
Wo liegen also die Mängel? Das Problem bei der Verwendung von regulärem Ausdruckscode zum Lesen von XML besteht darin, dass nicht zunächst überprüft wird, ob das XML wohlgeformt ist. Das bedeutet, dass es vor dem Lesen keine Möglichkeit gibt, festzustellen, ob das XML wohlgeformt ist. Außerdem stimmen einige wohlgeformte XML-Dateien möglicherweise nicht mit dem regulären Ausdruck überein und müssen daher später geändert werden.
Ich empfehle nie, reguläre Ausdrücke zum Lesen von XML zu verwenden, aber manchmal ist es aus Kompatibilitätsgründen die beste Möglichkeit, weil die regulären Ausdrucksfunktionen immer verfügbar sind. Verwenden Sie keine regulären Ausdrücke, um XML direkt vom Benutzer zu lesen, da Sie keine Kontrolle über das Format oder die Struktur solchen XMLs haben. Sie sollten immer eine DOM-Bibliothek oder einen SAX-Parser verwenden, um XML vom Benutzer zu lesen. XML mit DOM schreiben
Das Lesen von XML ist nur ein Teil der Gleichung. Wie schreibe ich XML? Der beste Weg, XML zu schreiben, ist die Verwendung des DOM. Listing 5 zeigt, wie das DOM die Buch-XML-Datei erstellt.
Listing 5. Buch-XML mit DOM schreiben
<?php
$books = array();
$books [] = array(
'title' => 'PHP Hacks',
'Autor' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
$books [] = array(
'title' => 'Podcasting-Hacks',
'Autor' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
$doc = new DOMDocument();
$doc->formatOutput = true;
$r = $doc->createElement( "books" );
$doc->appendChild( $r );
foreach( $books as $book )
{
$b = $doc->createElement( "book" );
$author = $doc->createElement( "author" );
$author->appendChild(
$doc->createTextNode( $book['author'] )
);
$b->appendChild( $author );
$title = $doc->createElement( "title" );
$title->appendChild(
$doc->createTextNode( $book['title'] )
);
$b->appendChild( $title );
$publisher = $doc->createElement( "publisher" );
$publisher->appendChild(
$doc->createTextNode( $book['publisher'] )
);
$b->appendChild( $publisher );
$r->appendChild( $b );
}
echo $doc->saveXML();
?>
|
Oben im Skript wird das Array „books“ mit einigen Beispielbüchern geladen. Diese Daten können vom Benutzer oder aus der Datenbank stammen.
Nachdem die Beispielbücher geladen wurden, erstellt das Skript ein neues DOMDocument und fügt ihm den Root-Books-Knoten hinzu. Das Skript erstellt dann Knoten für den Autor, den Titel und den Herausgeber jedes Buchs und fügt jedem Knoten Textknoten hinzu. Der letzte Schritt für jeden Buchknoten besteht darin, ihn erneut zu den Stammknotenbüchern hinzuzufügen.
Verwenden Sie am Ende des Skripts die Methode saveXML, um das XML an die Konsole auszugeben. (Sie können auch die Methode save verwenden, um eine XML-Datei zu erstellen.) Die Ausgabe des Skripts ist in Listing 6 dargestellt.
Listing 6. Ausgabe des DOM-Build-Skripts
%phpe4.php
<?xml version="1.0"?>
<Bücher>
<Buch>
<Autor>Jack Herrington</Autor>
<title>PHP Hacks</title>
<publisher>O'Reilly</publisher>
</Buch>
<Buch>
<Autor>Jack Herrington</Autor>
<Titel>Podcasting-Hacks</Titel>
<publisher>O'Reilly</publisher>
</Buch>
</Bücher>
%
|
Der wahre Wert der Verwendung des DOM besteht darin, dass das von ihm erstellte XML immer wohlgeformt ist. Aber was ist, wenn Sie mit dem DOM kein XML erstellen können?
XML in PHP schreiben
Wenn das DOM nicht verfügbar ist, kann XML mithilfe der Textvorlagen von PHP geschrieben werden. Listing 7 zeigt, wie PHP die Buch-XML-Datei erstellt.
Listing 7. Buch-XML in PHP schreiben
<?php
$books = array();
$books [] = array(
'title' => 'PHP Hacks',
'Autor' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
$books [] = array(
'title' => 'Podcasting-Hacks',
'Autor' => 'Jack Herrington',
'publisher' => "O'Reilly"
);
?>
<Bücher>
<?php
foreach( $books as $book )
{
?>
<Buch>
<title><?php echo( $book['title'] ); ?></title>
<Autor><?php echo( $book['author'] ?>
</Autor>
<publisher><?php echo( $book['publisher'] ?>
</Verlag>
</Buch>
<?php
}
?>
</Bücher>
|
Der obere Teil des Skripts ähnelt einem DOM-Skript. Der untere Teil des Skripts öffnet das Buch-Tag und durchläuft dann jedes Buch, wobei das Buch-Tag und alle internen Titel-, Autor- und Herausgeber-Tags erstellt werden.
Das Problem bei diesem Ansatz ist die Kodierung der Entitäten. Um sicherzustellen, dass Entitäten korrekt codiert werden, muss die Funktion htmlentities für jedes Element aufgerufen werden, wie in Listing 8 gezeigt.
Listing 8. Entitäten mit der Funktion htmlentities kodieren
<Bücher>
<?php
foreach( $books as $book )
{
$title = htmlentities( $book['title'], ENT_QUOTES );
$author = htmlentities( $book['author'], ENT_QUOTES );
$publisher = htmlentities( $book['publisher'], ENT_QUOTES );
?>
<Buch>
<title><?php echo( $title ); ?></title>
<author><?php echo( $author ); ?> </author>
<publisher><?php echo( $publisher ); >
</Verlag>
</Buch>
<?php
}
?>
</Bücher>
|
Hier wird das Schreiben von XML in einfachem PHP lästig. Sie denken, Sie hätten perfektes XML erstellt, aber sobald Sie versuchen, die Daten zu verwenden, stellen Sie fest, dass einige Elemente falsch codiert sind.
Abschluss
Es gibt immer viel Übertreibung und Verwirrung rund um XML. Es ist jedoch nicht so schwierig, wie Sie denken – insbesondere in einer so großartigen Sprache wie PHP. Sobald Sie XML verstanden und richtig implementiert haben, stehen Ihnen viele leistungsstarke Tools zur Verfügung. XPath und XSLT sind zwei solcher Tools, die es wert sind, studiert zu werden.