www.PHP-Crawler.de Translate into English Traduire cette page PHP-Crawler - Home PHP-Crawler - Home
   


  Home
    Hier geht´s zurück zur Startseite von PHP-Crawler.de

  Tutorial eintragen
    Hier könnt Ihr euer eigenes Tutorial eintragen.

  Tutorials
    Hier geht´s zurück zur Übersicht der Tutorials.

     Partnerseiten
     PHPWelt
     PHP Resource
     phpforum.de
     admin-wissen.de
     Belauscht.de
     www.z-online.de

   

  
Sponsoren
   Reifen - Bei uns können Sie Reifen besonders billig bestellen.
Hotel buchen - Hotelreservierung bei ehotel.de - Hotels weltweit.
Leuchten - Die schönsten Leuchten einfach online kaufen - im Lichtkaufhaus!!
Kindergeburtstag - Erfahren Sie wie ein Kindergeburtstag ein toller Erfolg wird.

 
PHP Crawler Tutorials
Nützliche Tutorials für euch zum lesen...


Willkommen bei dem Tutorialabschnitt von PHP-Crawler

Zurück zur Übersicht

Daten des Autors
Titel: Erstellen einer Newsanzeige mit XML und PHP
Autor: Nobody
Kategorie: PHP & XML
Verfasst am: 14.04.2006

Tutorial:
Ziel dieses Tutorials ist es, gezielt Informationen aus einer XML Datei mittels PHP zu ziehen. Als Beispielanwendung soll eine nützliche Anwendung dienen: Ein Newsmodul, mit dem man auch andere, befreundete Seiten mit den eigenen News versorgen kann - jedoch in ihrem eigenen Design. Dieser Artikel setzt allgemeine Kenntnisse in PHP voraus.



Hintergrund



Du möchtest News auf deiner Seite bereitstellen und diese im XML Format bereithalten. Da die XML Datei auch von fernen Servern aus abgerufen werden kann, können andere Webmaster, die wissen, wo genau die XML Datei liegt und wie sie aufgebaut ist, deine News auf ihren Seiten einbinden - jedoch in ihrem Design.



Die Datenstruktur



Am Anfang einer XML Anwendung steht immer das Design einer Datenstruktur: "Wie soll meine XML Datei aufgebaut sein, welche Tags verschachtele ich wie und wie soll ich sie nennen?" Fehler im Design ziehen wie überall im Softwaredesign Schwierigkeiten nach sich, deswegen sollte man hier schon einen Moment überlegen. Und auch wenn PHP nichts mit einer DTD anfangen kann, man selbst muß sich auf jeden Fall auf das zuvor festgelegte Datenstruktur halten, denn sonst klappt es nie mit dem Nachbarn.



Folgende XML Datei genügt meinen Ansprüchen als Newslieferant erst einmal:








<?xml version="1.0"?>


<news>

<item>

<meta>

<author>

<name type="official">Sebastian Will</name>

<name type="nick">junx</name>

<email>junx@gmx.net</email>

</author>

<title>Schema offiziell vom W3C freigegeben</title>

<date day="02" month="05" year="2001" />

</meta>

<text>

<short>Das W3C hat am 02. Mai 2001 die Recommendation für die XML Schema freigegeben.</short>

<long>Das W3C hat am 02. Mai 2001 die Recommendation für die XML Schema freigegeben. Sie soll

die bisherigen DTD's, die bisher für die Struktur eines XML Dokumentes sorgten ablösen.</long>

</text>

</item>

</news>





Die grobe Bedeutung sollte aufgrund der sprechenden Namen der Tags eigentlich klar sein: ein item stellt eine Newsnachricht dar, die meta Informationen wie Autor mit Namen und Nickname sowie Email Adresse, den Titel der Nachricht und ihr Erstellungsdatum bilden die Hintergrundinformationen, während short einen Kurztext der News und long den zugehörigen Langtext bietet.



Event handler und Layoutüberlegungen



PHP benutzt den XML Parser Expat von James Clark ( http://www.jclark.com/xml/expat.html ), um XML Dokumente verarbeiten zu können, und wie im Einführungsartikel Parsertypen erwähnt, handelt es sich dabei um einen SAX Parser. Demnach muß ich genau die event handler definieren, die ich für meine Aufgabe benötige. In meinem Fall wäre das nur der Handler für sich öffnende (und schließende) Tags und für character data.



Die News sollen auf meiner Seite etwa so erscheinen, was natürlich nur ein grober Entwurf ist, um das Prinzip zu verdeutlichen. Jetzt mit HTML Trickkisten um sich zu werfen, würde die Leserschaft unnötigerweise verwirren:



Schema offiziell vom W3C freigegeben



Von junx

Das W3C hat am 02. Mai 2001 die Recommendation für die XML Schema freigegeben.







<table border width="250">

<tr>

<td><strong>Schema offiziell vom W3C freigegeben</strong></td>

</tr>

<tr>

<td><small>Von junx <<a href="mailto:junx@gmx.net">junx@gmx.net</a></small></td>

</tr>

<tr>

<td>Das W3C hat am 02. Mai 2001 die Recommendation für

die XML Schema freigegeben. <a>[mehr...]</a></td>

</tr>

</table>





Der Newscontainer: Die Klasse News_item



Zur einfacheren Verwaltung der einzelnen News Beiträge lege ich jeden einzelnen in ein Objekt der Klasse News_item, die einfach die relevanten Daten speichert und auf Befehl in der oben gezeigten Tabellenform ausgibt. Alle News Beiträge werden in einem array gehalten, den ich ganz am Schluß durchlaufen kann:








<?php 

class News_item 

var 
$title

var 
$author_name null

var 
$author_nick null

var 
$author_email null

var 
$created_at null

var 
$short_text null

var 
$long_text null





function 
News_item($title$author_name$author_nick$author_email$created_at$short_text$long_text) { 

$this->title $title

$this->author_name $author_name

$this->author_nick $author_nick

$this->author_email $author_email

$this->created_at $created_at

$this->short_text $short_text

$this->long_text $long_text





function 
print_news() { 

?>



<table border width="250">

<tr>

<td><strong>
<?php echo $this->title?>
</strong></td>

</tr>

<tr>

<td><small>Von
<?php echo $this->author_nick?>
<

<a href="mailto:
<?php echo $this->author_email?>
">


<?php echo $this->author_email?>
</a>></small></td>

</tr>

<tr>

<td>
<?php echo $this->short_text?>
<a>[mehr...]</a></td>

</tr>

</table>


<?php 













Der Konstruktor füllt einfach die privaten Membervariablen der Klasse mit tatsächlichen Werten, die Methode print_news() bringt die Tabelle mit diesen Daten dann auf die Webseite.



Die 
eigentlichen Handler



Da wir einen SAX Parser benutzen
muß eine etwas kompliziertere Logik erfunden werdendamit wir unsere Newsitems aus der Datei gezogen und in den Speicher geladen bekommenWir haben handler für Startund Endtagssowie einen handler für Text zwischen den Tagsden sogenannten character data handlerIm character data handler bekommen wir nicht mitzwischen welchen Tags wir uns gerade befindenzu welchem Tag diese Zeichen also letztendlich gehörendas müssen wir uns selbst merkenindem wir eine entsprechende Variable im Start handler setzen.



Die 
Handler haben also grob beschrieben folgende Funktionalität:



Start handlerMerken des aktuellen Tags in der globalen Variable statesowie das Zusammenbasteln des DatumsDieses wird nur als Attribut des Tags date mitgeliefert und ist somit nur in diesem Handler verfügbar.

End handlerErstellen eines neuen News_item Objectswenn man auf den Tag trifftdenn dann sollte man alle nötigen Informationen zusammen haben.

Character data handlerAnhand der Variable state wird entschiedenzu welchem Tag die Daten gehören.



Globale Variablen



Bevor ein neues News_item Objekt erstellt wird
werden die relevanten Daten in globalen Variablen zwischengespeichert, die wie folgt benannt sind:







<? 

$news_file "news.xml"

$news_items null

$state null



$title null

$author_name null

$author_nick null

$author_email null

$created_at null

$short_text null

$long_text null

?>









$news_file verweist auf das XML Dokument, daß als Datenquelle herhalten wird, $news_items ist der Array auf News_items Objekten, der später bei der Ausgabe durchlaufen wird und $state ist die Merkvariable, die im Start handler gesetzt und im character data handler gelesen wird. Die Verwendung der anderen Variablen sollte eigentlich klar sein.



Der Start handler








<? 

function start_hdl($parser$tag$attribs) { 

global 
$state

global 
$created_at



$my_tag strtoupper($tag); 

$state $my_tag



if (
$my_tag == "NAME") { 

// depending on the attribute, we have the nickname or the realname of the author 

$state strtoupper($attribs["TYPE"]); 

} else if (
$my_tag == "DATE") { 

// The second tag we're reacting on in the starting element handler. 

// the others will be dealt with in the cdata handler, depending on 

// the variable $state 

$state "CREATED_AT"

$created_at $attribs["day"].".".$attribs["month"].".".$attribs["year"]; 

} else { 

// unsupported or irrelevant tag found 

// do nothing 





?>









Wir bekommen den Namen des Tags mit dem Parameter $tag und dessen Attribute, sofern vorhanden, im Parameter $attribs als Array mitgeliefert. Wenn man sich unsere XML Datenstruktur ins Gedächtnis ruft, bemerkt man, daß es nur zwei Tags gibt, die mit Attributen bestückt sind: name und date. Nur diese zwei Tags muß ich im Start handler auch gezielt weiter bearbeiten, da ich nur in diesem handler an die Attribute herankomme.



Handelt es sich um den Tag name, bekommen wir nur durch das zusätzliche Attribute type heraus, ob es sich um den offiziellen (Real-) Namen oder den Spitznamen (nick) handelt, dementsprechend setzen wir den Status auch nicht auf name, sondern auf den Wert dieses Attributes.



Handelt es sich um das Datum, basteln wir uns das direkt in diesem handler zusammen. Ich habe die Datumsangabe als Sammlung von Attributen gewählt, da man so einfach das amerikanische Datumsformat abbilden kann, wenn das gewünscht sein sollte.



Der character data handler








<? 

function cdata_hdl($parser$data) { 

global 
$state

global 
$title

global 
$author_name

global 
$author_nick

global 
$author_email

global 
$created_at

global 
$short_text

global 
$long_text



if (
trim($data) != "") { 

if (
$state == "TITLE") { 

$title $data

} else if (
$state == "OFFICIAL") { 

$author_name $data

} else if (
$state == "NICK") { 

$author_nick $data

} else if (
$state == "EMAIL") { 

$author_email $data

} else if (
$state == "SHORT") { 

$short_text $data

} else if (
$state == "LONG") { 

$long_text $data





}

?>









Da auch whitespaces zwischen den Tags als character data gelten, und ich die Tags durch Tabulatoren so eingerückt habe, daß das menschliche Auge auch etwas davon hat, werden wir auf Unmengen von character data treffen, die einfach aus einer gewissen Anzahl von Tabulatoren oder anderen whitespaces besteht. Durch ein trim($data) kann ich diese nutzlosen Informationen herausfiltern und mir so ein wenig Rechenzeit sparen.



Ansonsten bekomme ich durch die Variable $state heraus, in welchem Tag ich mich gerade befinde und kann so der entsprechenden Variable das aktuelle Datenpaket zuweisen.



Der End handler








<? 

function end_hdl($parser$tag) { 

global 
$news_items

global 
$title

global 
$author_name

global 
$author_nick

global 
$author_email

global 
$created_at

global 
$short_text

global 
$long_text



$my_tag strtoupper($tag); 



// We react only if we find a , because then we have gathered enough 

// data to create a new news-object in our array 

if ($my_tag == "ITEM") { 

$news_items[] = new News_item($title$author_name$author_nick$author_email$created_at$short_text$long_text);



$title null

$author_name null

$author_nick null

$author_email null

$created_at null

$short_text null

$long_text null





?>









Hier warte ich nur darauf, daß der Tag item sich schließt, da ich dann alle notwendigen Daten haben sollte und ich dem Array $news_items ein neues Objekt News_item mit den gesammelten Daten hinzufügen kann. Anschließend werden alle globalen Variablen zurückgesetzt, damit ich nicht durcheinanderkomme, falls in der XML Datei z.B. der Autor-Tag im zweiten News Beitrag vergessen wurde.



Zusammenfassung



Wichtig ist eigentlich nur, die Zuordnung zwischen character data und dem dazugehörenden Tag nicht zu vermasseln. Wenn man, wie ich hier, dazu eine globale Variable heranzieht, stellt das überhaupt kein Problem dar und man kann auf einfache Art und Weise auf der eigenen Seite und auf fremden Seiten News bereitstellen. Damit fremde Webseiten von den eigenen News profitieren können, sollte man den gesamten Quelltext als include-Datei weitergeben, um die Optik anzupassen, muß lediglich die Methode print_news() angepaßt werden - alles weitere läuft dann automatisch ab.