XML RSS Feed mit PHP und XML Parser einlesen

» Mit PHP kann man über die Bordmittel ganz einfach und schnell XML RSS Feeds einlesen und verarbeiten, ohne sich mit irgendwelchen "regexen" zu verhäddern. «

Es gibt die Möglichkeit den Inhalt eines RSS Feeds ganz normal einzulesen und diesen dann aufwendig über regex (regular expression zu Deutsch: 'regulärer Ausdruck') auseinander zu nehmen und die einzelnen Bestandteile in arrays zu speichern. Doch meistens fangen die Probleme mit den Einsatz von regex dann erst richtig an. Es geht aber auch anders und zwar mit den eingebauten Bordmitteln von PHP zur Verarbeitung von XML-Daten (RSS Feeds sind im Prinzip nichts anderes als XML­-Dokumente).

Um die PHP-eigenen Befehle richtig nutzen zu können, benötigt man vier Funktionen. Eine Hauptfunktion sowie drei Unterfunktionen, die für die Verarbeitung der Start- und Endtags sowie CDATA zuständig sind. Ein RSS Feed ist primär in dieser Art aufgebaut:

<?xml version="1.0" encoding="UTF-8"?>
    <rss version="2.0">
        <channel>
            <title>Name des RSS Feed</title>
            <description>Feed Beschreibung</description>
            <language>de</language>
            <link>http://xml-rss.de</link>
            <lastBuildDate>Sat, 1 Jan 2000 00:00:00 GMT</lastBuildDate>
            <item>
                <title>Titel der Nachricht</title>
                <description>Die Nachricht an sich</description>
                <link>http://xml-rss.de/link-zur-nachricht.htm</link>
                <pubDate>Sat, 1. Jan 2000 00:00:00 GMT</pubDate>
                <guid>01012000-000000</guid>
            </item>
        </channel>
    </rss>

Die gewünschten Informationen sind immer in tags eingeschlossen. Es gibt einen Starttag wie z.B. <title>, die eingeschlossene Information ('Titel der Nachricht') sowie einen Endtag (</title>). Unsere drei Unterfunktionen kümmern sich jeweils um die einzelnen Abschnitte (Starttag, Information, Endtag) und arbeiten unserem Hauptscript (Funktion) zu.

Die erste Unterfunktion für den Starttag:

    function xmlstart($pars, $tagn, $attr){
        global $insi, $tag, $titl, $i,
        $desc, $link, $pubd, $guid, $xdat;
        if($insi){
            $tag = $tagn;
        }elseif($tagn == "ITEM"){
            $insi = true;
        }
    }

Der Name der Funktion (in diesem Beispiel 'xmlstart') ist frei wählbar, genauso wie die ganzen verwendeten Variablennamen, doch wer diese ändert, sollte natürlich auch darauf achten, dieses konsequent in allen Funktionen umzusetzen, da die Variablen Funktionsübergreifend also 'global' sind.

In dem ersten Abschnitt definieren wir die von uns gebrauchten Variablen als globale Variablen (dieses müssen wir in JEDER beteiligten Funktion machen). Das hat den Hintergrund bzw. Sinn, das uns die Wert in den Variablen erhalten bleiben, wenn wir zwischen den einzelnen Funktionen "hin-und-her-springen", ansonsten würden die Werte beim verlassen einer Funktion verloren gehen.

Wir haben nun mehrer Variablen als global deklariert:

$insi = wird benutzt als Container für einen bestimmten Status, diese Variable wird den Wert 'true' (wahr) oder 'false' (falsch) beinhalten.

$tag = bekommt von unserem Hauptscript/Hauptfunktion die Bezeichnung des gerade abgefragten RSS-tags zugewiesen (z.B. 'title', 'description', etc...)

$i = ist der Container für eine fortlaufende Nummerierung.

$xdat = ist unser späteres Ergebnis-Array, in dem sämtliche Informationen des eingelesenen RSS-Feeds strukturiert enthalten sein werden.
Die folgenden Variablen nehmen immer die jeweiligen Inhalte der tags auf:
$titl = Inhalt des 'title'-tags (Titel der Nachricht)

$desc = Inhalt des 'description'-tags (Inhalt der Nachricht)

$link = Inhalt des 'link'-tags (Internetadresse/URL zur Nachricht)

$pubd = Inhalt des 'pubdate'-tags (Veröffentlichungsdatum der Nachricht)

$guid = Wert des 'guid'-tags (Globally Unique IDentifier übersetzt: 'Globales einmaliges Identifizierungsmerkmal der Nachricht')
Diese Variablen sind nun alle global und für jede unserer benötigten Funktionen verfügbar.

Bei der folgenden 'if'-Schleife wird abgefragt ob $tagn den Wert 'item' besitzt und die Variable $insi auf 'true' gesetzt. Da es sich hierbei um unsere Starttag-Funktion handelt, wird nur geprüft ob unser Script 'zur Zeit' im RSS Feed bei den 'items' angekommen ist (das Script liest einen RSS Feed Zeile für Zeile ein) und gibt dann praktisch 'grünes Licht' zum einlesen und verarbeiten der Inhalte/Daten. Damit haben wir eine unserer Unterfunktionen bereits abgeschlossen.

Die nächste kümmert sich nun um die Daten/Inhalte:

    function cdatahan($pars, $data){
        global $insi, $tag, $titl, $desc,
        $link, $pubd, $guid, $i, $xdat;
        if($insi){
            switch($tag){
                case "TITLE":
                    $titl .= $data;
                    break;
                case "DESCRIPTION":
                    $desc .= $data;
                    break;
                case "LINK":
                    $link .= $data;
                    break;
                case "PUBDATE":
                    $pubd .= $data;
                    break;
                case "GUID":
                    $guid .= $data;
                    break;
            }
        }
    }

Das ist unsere Funktion für die Verarbeitung der eigentlichen Daten/Inhalte. Der erste Abschnitt dürfte klar sein, hier werden wieder unsere globalen Variablen definiert. Anschliessend wird abgefragt ob unsere $insi-Variable den Wert 'true' hat und unser Hauptscript sich also im 'item'-Bereich des RSS Feeds befindet. Ansonsten wird alles übersprungen, so lange bis $insi wieder 'true' ist.
Im letzen Part werden die Inhalte der tags ('title', 'description', etc..) den jeweiligen Variablen zugeordnet. Damit unser späteres Ergebnis-Array ($xdat) alle Werte und Inhalte schön sauber sortiert hat.
Und schon kommen wir zu unserer letzten Unterfunktion, die Verarbeitung der Endtags.

    function xmlendhd($pars, $tagn){
        global $insi, $tag, $titl, $desc,
        $link, $pubd, $guid, $i, $xdat;
        if($tagn == "ITEM"){
            $xdat[$i][0] = htmlspecialchars(trim($titl));
            $xdat[$i][1] = htmlspecialchars(trim($desc));
            $xdat[$i][2] = trim($link);
            $xdat[$i][3] = trim($pubd);
            $xdat[$i][4] = trim($guid);       
            $i++;
            $titl = "";
            $desc = "";
            $link = "";   
            $pubd = "";
            $guid = "";
            $insi = false;
        }
    }

Gleiches Prinzip wie shon vorher, wir definieren unsere Variablen als global. Anschliessend wird abgefragt ob die Variable $tagn den Wert 'item' hat und somit der Rest der Funktion in Aktion treten darf oder nicht. Wenn sie weiterarbeiten darf, teilt sie nun die einzelnen Daten des Feeds in unserer Ergebnis-Variablen ($xdat (array)). Während man bei den anderen Funktionen eigentlich nichts ändern braucht oder sollte, kann man bei dieser letzten die Struktur des Ergebnis-Arrays beeinflussen. Wie man im Script sieht ist unsere jetzte Aufteilung wie folgt:
$xdat[0][1] = 1. Datensatz des Feeds mit dem Inhalt des 'title'-tag
$xdat[0][2] = 1. Datensatz des Feeds mit dem Inhalt des 'description'-tag
$xdat[0][3] = 1. Datensatz des Feeds mit dem Inhalt des 'link'-tag
$xdat[0][4] = 1. Datensatz des Feeds mit dem Inhalt des 'pubdate'-tag
$xdat[0][5] = 1. Datensatz des Feeds mit dem Inhalt des 'guid'-tag
anschliessend für der nächste Datensatz des Feeds (nächste Nachricht) folgen:
$xdat[1][1] = 2. Datensatz des Feeds mit dem Inhalt des 'title'-tag
$xdat[1][2] = 2. Datensatz des Feeds mit dem Inhalt des 'description'-tag
$xdat[1][3] = 2. Datensatz des Feeds mit dem Inhalt des 'link'-tag
$xdat[1][4] = 2. Datensatz des Feeds mit dem Inhalt des 'pubdate'-tag
$xdat[1][5] = 2. Datensatz des Feeds mit dem Inhalt des 'guid'-tag
usw...
In unserem Script wird nach der Aufteilung noch unsere Variable $i um einen Wert erhöht ($i++ = $i + 1), damit wir auch fortlaufende Datensätze erhalten und nicht immer der eine überschrieben wird. Zum Schluss werden sämtliche Variablen inhaltlich neutralisiert oder auch gelöscht, damit nicht irgendwelche Datenbestandteile doppelt auftauchen, was leicht passieren kann, wenn Variablen als global definiert sind.
Damit haben wir unsere Hilfs-/ Unterfunktionen abgeschlossen und kommen nun direkt zum Hauptscript...
      global $insi, $tag, $titl, $desc,
    $link, $pubd, $guid, $i, $xdat;
    $titl = "";
    $desc = "";
    $link = "";
    $pubd = "";
    $guid = "";   
    $xdat = array();
    $i = 0;
    $xml = xml_parser_create();
    xml_set_element_handler($xml, "xmlstart", "xmlendhd");
    xml_set_character_data_handler($xml, "cdatahan");
    $fp = fopen(LABSPATH.'xml/site-rss2.xml',"r")
    or die("Error reading RSS data.");
    while($data = fread($fp, 4096)){
        xml_parse($xml, $data, feof($fp))
        or die(sprintf("XML error: %s at line %d",
        xml_error_string(xml_get_error_code($xml)),
        xml_get_current_line_number($xml)));
    }
    fclose($fp);
    xml_parser_free($xml);

Wie solls auch anders sein ... zu Anfang definieren wir auch hier die globalen Variablen. Anschliessend neutralisieren (löschen) wir diese inhaltlich um wirklich "frische" Variablen zu haben. $xdat wird noch schnell als array definiert und $i setzen wir auf 0 (wer möchte kann hier auch die Datensätze bei 1 starten lassen und muss dann hier entsprechend 1 vorgeben).
Nun kommen wir zum "Eingemachten"...

    $xml = xml_parser_create();

Wir erstellen ein neues XML-Parser-Objekt.

    xml_set_element_handler($xml, "xmlstart", "xmlendhd");

Die "Händler" werden definiert, d.h. unsere zuvor erstellen Unterfunktionen werden nun als Verarbeiter aufgeführt: "xmlstart" für unsere Funktion xmlstart() und "xmlendhd" für xmlendhd().

    xml_set_character_data_handler($xml, "cdatahan");

Unsere zuständige Funktion für die Verarbeitung der eigentlichen Daten wird hier angegeben, definiert.
 
    $fp = fopen('dateiname.xml',"r")
    or die("Error reading RSS data.");

Nun gehts los ... Es wird die gewünschte Datei des RSS Feeds geöffnet. Wo jetzt 'dateiname.xml' steht muss dann natürlich die entsprechende Adresse/URL zu dem einzulesenden Feed eingetragen bzw. geändert werden. Wenn es Probleme beim Aufruf der .xml-Datei geben sollte (z.B. Server nicht erreichbar) dann soll das Script abbrechen 'or die'.

    while($data = fread($fp, 4096)){
        xml_parse($xml, $data, feof($fp))
        or die(sprintf("XML error: %s at line %d",
        xml_error_string(xml_get_error_code($xml)),
        xml_get_current_line_number($xml)));
    }

In diesem Abschnitt werden die einzelnen Zeilen des RSS Feeds nun Stück für Stück eingelesen und verarbeitet (d.h. auf unsere Unterfunktionen weitergegeben). Auch hier soll unser Script wieder 'sterben' ('or die') wenn es beim einlesen zu Problemen kommen sollte und wir keine Endlosschleife bekommen.

    fclose($fp);
    xml_parser_free($xml);

Zum Schluss wird unsere Verbindung (die wir zum RSS Feed aufgebaut hatten) wieder geschlossen und unser System von unnötigem Ballast befreit (die vollgestopfte Variable $xml wird geleert, da sich unsere Daten ja nun in $xdat befinden).

Das war es auch schon. Nun haben wir den gesamten Inhalt des eingelesenen RSS Feeds in unserem Ergebnis-Array ($xdat), schön säuberlich sortiert aufgeführt und ist bereit für die weitere Verarbeitung. Die Variable/Array sind nun in etwa so aus:

    Array(
        [0] => Array
            (
              [0] => Titel der ersten Nachricht
              [1] => Inhalt der ersten Nachricht
              [2] => Link zur ersten Nachricht
              [3] => Veröffentlichungsdatum
              [4] => GUID der ersten Nachricht
           )
         [1] => Array
            (
              [0] => Titel der zweiten Nachricht
              [1] => Inhalt der zweiten Nachricht
              [2] => Link zur zweiten Nachricht
              [3] => Veröffentlichungsdatum
              [4] => GUID der zweiten Nachricht
           )
    )

Wer nun auf den Titel der zweiten Nachricht zugreifen möchte, erreicht diese direkt über:    


$xdat[1][0]
Nicht durch die '1' durcheinander bringen lassen, da unser Array mit 0 beginnt ist die erste Nachricht auf Platz '0', die zweite auf Platz '1', etc... da die 0 ebenfalls als Position mit gezählt wird.
Es sei den wir haben vorher unsere Variable $i mit dem Startwert '1' definiert, dann ist die erste Nachricht unter '1', die zweite unter '2', etc... zu finden. Doch wer öfters mit PHP programmiert, sollte sich ruhig an die '0' gewöhnen. 
Nachdem man nun mit den Daten ein wenig 'rumhantiert', kann man auch selbstverständlich gleich wieder einen neuen RSS Feed mit den speziellen Bordmitteln von PHP generieren.
 
Bild einer Zeitung, Zeitschrift als Symbol für Newsletter

Newsletter

Jetzt unseren kostenlosen Newsletter abonnieren und immer aktuell informiert sein.


Ein Bookmark Buch

Bookmark

Diese Seite als Lesezeichen (Bookmark) hinzufügen, bei...

Furl YahooMyWeb Google Bookmark del.icio.us Tausendreporter Webnews yigg it Mister Wong co.mments TailRank Spurl Digg blinkbits BlinkList Reddit connotea
Symbol der RSS Feeds

RSS Feeds

Bleiben Sie auf dem Laufendem mit unseren Informationsfeeds:

[Website-Feeds]: Logo RSS-Feed Version 1.0 Logo RSS-Feed Version 2.0 Logo RSS-Feed Version ATOM


©copyright 2008 by xml-rss.de - all rights reserved
Websolution & Development powered by dmp|cda

    H   A   U   P   T   M   E   N   Ü

KW 18 - Montag, 01. Mai 2017