Zugriff auf die neuesten Beiträge / Einbindung in eigene Seiten
-
Hallo,
immer wieder kommt der Wunsch auf, die aktuellen Beiträge in anderen Seiten einzubinden oder einen ActiveDesktop etc. für das Forum zu bekommen.
Ich habe eine Funktion realisiert, die halbstündlich aktualisiert eine XML-Datei mit einer Übersicht aller Threads (ohne Neuigkeiten, OT) generiert.
Die Datei ist ladbar unter
http://www.c-plusplus.net/php/xmlnews/cpp-de.xml
Wobei beim Download in einem Browser die XML sofort via XSL nach HTML transformiert wird (beim IE - nicht in Opera, NS).
Ansonsten sieht die XML ungefähr so aus:
<?xml version="1.0" encoding="ISO-8859-1"?> <?xml-stylesheet type="text/xsl" href="http://www.c-plusplus.net/php/xmlnews/cpp_channels_genhtml.xsl"?> <topics xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://www.c-plusplus.net/php/xmlnews/cpp_channels.xsd"> <header> <channel>C/C++-Forum global</channel> <copyrightowner>www.c-plusplus.net</copyrightowner> <language>de</language> <update_mins>30</update_mins> <timestamp>1058621537</timestamp> <date>19.07.2003</date> <time>15:32</time> <comment>Dies ist der allgemeine Newschannel für alle technischen Themen des Boards.</comment> </header> <topic> <title>Mehrsprachige Programme erstellen</title> <link>http://www.c-plusplus.net/forum/topic,42925.html</link> <timestamp>1058621481</timestamp> <date>19.07.2003</date> <time>15:31</time> <poster>Alexander Sulfrian</poster> <forum>Borland C++ Builder (VCL/CLX)</forum> <forum_link>http://www.c-plusplus.net/forum/forum,2.html</forum_link> <cat>Entwicklungssysteme</cat> <cat_link>http://www.c-plusplus.net/forum/index.php?c=1</cat_link> </topic> <topic> ... </topic> </topics>
Der Aufbau der Datei ist als XML-Schema beschrieben und befindet sich unter:
http://www.c-plusplus.net/php/xmlnews/cpp_channels.xsdDamit werden folgenden Anwendungen möglich:
"Poller", Tool das regelmäßig die XML-Datei abfragt und in einer Applikation darstellt - kann z.B. ein Java- oder C++-Client sein.
Active-Desktop-Hintergrund, dazu muß aber eine schönere XSL-Transformation geschrieben werden mit "bunterem" HTML
andere Seiten können die letzten 5 bis 10 aktiven Threads anzeigen, indem über ein PHP-Script die XML geladen und geparst wirdUnd das alles ohne zusätzliche Last für die Datenbank - es sind nur 2 Abfragen pro Stunde, ansonsten wird einfach nur immer die XML vom Server abgerufen. Und falls jemand nämlich das HTML vom Forum parsen will ist das natürlich viel schwieriger, wenn das Layout ein wenig geändert wird.
-
Hier gibt's nun gleich einen PHP-Client, der die Datei lädt und eine Seite daraus formatiert:
Demo: http://www.c-plusplus.net/php/xmlnews/news_demo.php
Der Parser verwendet die SAX-API. Hier der Quellcode:
<?php /* Demo zum einlesen des XML-Newschannel nach php verwendet SAX als XML-Parser Marcus Bäckmann ;) www.c-plusplus.net */ $file = "http://www.c-plusplus.net/php/xmlnews/cpp-de.xml"; $numberofa = 0; $maxa = 10; // Anzahl gezeigter Artikel $inside_header = "false"; $topic_title = ""; $topic_link = ""; $topic_timestamp = ""; $topic_date = ""; $topic_time = ""; $topic_poster = ""; $topic_forum = ""; $topic_forum_link = ""; $topic_cat = ""; $topic_cat_link = ""; $header_channel = ""; $header_copyrightowner = ""; $header_update_mins = ""; $header_language = ""; $header_timestamp = ""; $header_date = ""; $header_time = ""; $header_comment = ""; $last_pcdata = ""; function pageHeader() { print("<html><head/><body>"); } function pageFooter() { global $header_channel; global $header_copyrightowner; global $header_language; global $header_update_mins; global $header_timestamp; global $header_date; global $header_time; global $header_comment; print("<p/>Alle Rechte vorbehalten: "); print("<a href=\"http://".$header_copyrightowner."\">".$header_copyrightowner."</a><p/>"); print("Update alle ".$header_update_mins." Minuten"); print("</body></html>"); } function printHeader() { global $header_channel; global $header_copyrightowner; global $header_language; global $header_update_mins; global $header_timestamp; global $header_date; global $header_time; global $header_comment; print("Aktuelle Beiträge aus <b>".$header_channel."</b><p/>"); print($header_comment."<p/>"); print("Stand: ".$header_date." ".$header_time."<p/>"); } function printTopic() { global $topic_title; global $topic_link; global $topic_timestamp; global $topic_date; global $topic_time; global $topic_poster; global $topic_forum; global $topic_forum_link; global $topic_cat; global $topic_cat_link; print("<p>"); print("<a href=\"".$topic_cat_link."\"\>".$topic_cat."</a>::"); print("<a href=\"".$topic_forum_link."\"\>".$topic_forum."</a>::"); print("<a href=\"".$topic_link."\"\>".$topic_title."</a><br>"); print("von ".$topic_poster." am ".$topic_date." um ".$topic_time."<p>"); } // XML-Parser beginnt hier function startElement($parser, $name, $attrs) { global $inside_header; global $last_pcdata; switch ($name) { case "HEADER": $inside_header = "true"; break; } $last_pcdata = ""; } function endElement($parser, $name) { global $print; global $numberofa; global $maxa; global $last_pcdata; global $inside_header; global $topic_title; global $topic_link; global $topic_timestamp; global $topic_date; global $topic_time; global $topic_poster; global $topic_forum; global $topic_forum_link; global $topic_cat; global $topic_cat_link; global $header_channel; global $header_copyrightowner; global $header_language; global $header_update_mins; global $header_timestamp; global $header_date; global $header_time; global $header_comment; if ($numberofa < $maxa) { switch ($name) { case "HEADER": printHeader(); $inside_header = "false"; break; case "CHANNEL": $header_channel = $last_pcdata; break; case "COPYRIGHTOWNER": $header_copyrightowner = $last_pcdata; break; case "LANGUAGE": $header_language = $last_pcdata; break; case "UPDATE_MINS": $header_update_mins = $last_pcdata; break; case "COMMENT": $header_comment = $last_pcdata; break; case "TOPIC": printTopic(); $numberofa++; break; case "TITLE": $topic_title = $last_pcdata; break; case "LINK": $topic_link = $last_pcdata; break; case "TIMESTAMP": if ($inside_header == "true") $header_timestamp = $last_pcdata; else $topic_timestamp = $last_pcdata; break; case "DATE": if ($inside_header == "true") $header_date = $last_pcdata; else $topic_date = $last_pcdata; break; case "TIME": if ($inside_header == "true") $header_time = $last_pcdata; else $topic_time = $last_pcdata; break; case "POSTER": $topic_poster = $last_pcdata; break; case "FORUM": $topic_forum = $last_pcdata; break; case "FORUM_LINK": $topic_forum_link = $last_pcdata; break; case "CAT": $topic_cat = $last_pcdata; break; case "CAT_LINK": $topic_cat_link = $last_pcdata; break; } } $last_pcdata = ""; } function characterData($parser, $data) { global $last_pcdata; $last_pcdata .= htmlentities($data); } pageHeader(); $xml_parser = xml_parser_create(); xml_set_element_handler($xml_parser, "startElement", "endElement"); xml_set_character_data_handler($xml_parser, "characterData"); if (!($fp = fopen($file, "r"))) { die("could not open XML input ".$file); } while ($data = fread($fp, 4096)) { if (!xml_parse($xml_parser, $data, feof($fp))) { die(sprintf("XML error: %s at line %d", xml_error_string(xml_get_error_code($xml_parser)), xml_get_current_line_number($xml_parser))); } } xml_parser_free($xml_parser); pageFooter(); ?>
Verwendet wird (eine leicht variierte Version) des Parsers z.B. auf der Startseite www.c-plusplus.net rechts.