A program alapja a myRSSParser class, amely kimondottan RSS 2.0 forrásokra lett megírva. Ebből adódóan hiába próbálunk beleadni más forrásokat valószínűleg hibákat fogunk kapni. A program alapvetően rémesen egyszerű. Először is szükségünk van egy Parser-re, amely a kapott RSS forrást darabokra szedi. Ennek a kódja így fest:
class myRSSParser
{
# keeps track of current and preceding elements
var $tags = array();
# array containing all feed data
var $output = array();
# return value for display functions
var $retval = "";
# constructor for new object
function myRSSParser($file)
{
# instantiate xml-parser and assign event handlers
$xml_parser = xml_parser_create("");
xml_set_object($xml_parser, $this);
xml_set_element_handler($xml_parser, "startElement", "endElement");
xml_set_character_data_handler($xml_parser, "parseData");
# open file for reading and send data to xml-parser
$fp = @fopen($file, "r") or die("myRSSParser: Could not open $file for input");
while($data = fread($fp, 4096)) {
xml_parse($xml_parser, $data, feof($fp)) or die(
sprintf("myRSSParser: Error %s at line %d
",
xml_error_string(xml_get_error_code($xml_parser)),
xml_get_current_line_number($xml_parser))
);
}
fclose($fp);
# dismiss xml parser
xml_parser_free($xml_parser);
}
function startElement($parser, $tagname, $attrs=array())
{
# RSS 2.0 - ENCLOSURE
if($tagname == "ENCLOSURE" && $attrs) {
$this->startElement($parser, "ENCLOSURE");
foreach($attrs as $attr => $attrval) {
$this->startElement($parser, $attr);
$this->parseData($parser, $attrval);
$this->endElement($parser, $attr);
}
$this->endElement($parser, "ENCLOSURE");
}
# check if this element can contain others - list may be edited
if(preg_match("/^(RDF|RSS|CHANNEL|IMAGE|ITEM)/", $tagname)) {
if($this->tags) {
$depth = count($this->tags);
list($parent, $num) = each($tmp = end($this->tags));
if($parent) $this->tags[$depth-1][$parent][$tagname]++;
}
array_push($this->tags, array($tagname => array()));
} else {
if(!preg_match("/^(A|B|I)$/", $tagname)) {
# add tag to tags array
array_push($this->tags, $tagname);
}
}
}
function endElement($parser, $tagname)
{
if(!preg_match("/^(A|B|I)$/", $tagname)) {
# remove tag from tags array
array_pop($this->tags);
}
}
function parseData($parser, $data)
{
# return if data contains no text
if(!trim($data)) return;
$evalcode = "\$this->output";
foreach($this->tags as $tag) {
if(is_array($tag)) {
list($tagname, $indexes) = each($tag);
$evalcode .= "[\"$tagname\"]";
if(${$tagname}) $evalcode .= "[" . (${$tagname} - 1) . "]";
if($indexes) extract($indexes);
} else {
if(preg_match("/^([A-Z]+):([A-Z]+)$/", $tag, $matches)) {
$evalcode .= "[\"$matches[1]\"][\"$matches[2]\"]";
} else {
$evalcode .= "[\"$tag\"]";
}
}
}
eval("$evalcode = $evalcode . '" . addslashes($data) . "';");
}
# display a single channel as HTML
function display_channel($data, $limit)
{
extract($data);
if($IMAGE) {
# display channel image(s)
foreach($IMAGE as $image) $this->display_image($image);
}
if($TITLE) {
# display channel information
$this->retval .= "\n";
if($DESCRIPTION) $this->retval .= "$DESCRIPTION
\n\n";
$tmp = array();
if($PUBDATE) $tmp[] = "Published: $PUBDATE";
if($COPYRIGHT) $tmp[] = "Copyright: $COPYRIGHT";
if($tmp) $this->retval .= "" . implode("
\n", $tmp) . "
\n\n";
$this->retval .= "\n\n";
}
if($ITEM) {
# display channel item(s)
foreach($ITEM as $item) {
$this->display_item($item, "CHANNEL");
if(is_int($limit) && --$limit <= 0) break; } } } # display a single image as HTML function display_image($data, $parent="") { extract($data); if(!$URL) return; $this->retval .= "";
if($LINK) $this->retval .= "";
$this->retval .= "retval .= " width=\"$WIDTH\" height=\"$HEIGHT\"";
$this->retval .= " border=\"0\" alt=\"$TITLE\">";
if($LINK) $this->retval .= "";
$this->retval .= "
\n\n";
}
# display a single item as HTML
function display_item($data, $parent)
{
extract($data);
if(!$TITLE) return;
$this->retval .= "";
if($LINK) $this->retval .= "";
$this->retval .= stripslashes($TITLE);
if($LINK) $this->retval .= "";
$this->retval .= "";
if(!$PUBDATE && $DC["DATE"]) $PUBDATE = $DC["DATE"];
if($PUBDATE) $this->retval .= " ($PUBDATE)";
$this->retval .= "
\n";
# use feed-formatted HTML if provided
if($CONTENT["ENCODED"]) {
$this->retval .= "" . stripslashes($CONTENT["ENCODED"]) . "
\n";
} elseif($DESCRIPTION) {
$this->retval .= "" . stripslashes($DESCRIPTION) . "
\n\n";
}
# RSS 2.0 - ENCLOSURE
if($ENCLOSURE) {
$this->retval .= "Media: ";
$this->retval .= $ENCLOSURE['TYPE'];
$this->retval .= " ({$ENCLOSURE['LENGTH']} bytes)
\n\n";
}
if($COMMENTS) {
$this->retval .= "";
$this->retval .= "Comments";
$this->retval .= "
\n\n";
}
}
function fixEncoding($input, $output_encoding)
{
if(!function_exists('mb_detect_encoding')) return $input;
$encoding = mb_detect_encoding($input);
switch($encoding) {
case 'ASCII':
case $output_encoding:
return $input;
case '':
return mb_convert_encoding($input, $output_encoding);
default:
return mb_convert_encoding($input, $output_encoding, $encoding);
}
}
# display entire feed as HTML
function getOutput($limit=false, $output_encoding='UTF-8')
{
$this->retval = "";
$start_tag = key($this->output);
switch($start_tag) {
case "RSS":
# new format - channel contains all
foreach($this->output[$start_tag]["CHANNEL"] as $channel) {
$this->display_channel($channel, $limit);
}
break;
case "RDF:RDF":
# old format - channel and items are separate
if(isset($this->output[$start_tag]['IMAGE'])) {
foreach($this->output[$start_tag]['IMAGE'] as $image) {
$this->display_image($image);
}
}
foreach($this->output[$start_tag]['CHANNEL'] as $channel) {
$this->display_channel($channel, $limit);
}
foreach($this->output[$start_tag]['ITEM'] as $item) {
$this->display_item($item, $start_tag);
}
break;
case "HTML":
die("Error: cannot parse HTML document as RSS");
default:
die("Error: unrecognized start tag '$start_tag' in getOutput()");
}
return $this->fixEncoding($this->retval, $output_encoding);
}
# return raw data as array
function getRawOutput($output_encoding='UTF-8')
{
return $this->fixEncoding($this->output, $output_encoding);
}
}
Miután ezt felmásoltuk a szerverre jön maga a fájl, amely kiiratja az RSS hírforrást. Ebben a fájlban végezhetünk el különböző beállításokat értelemszerűen értelmezve a következő változókat:
$FEEDURL - Ez az RSS címe pl.: http://www.sg.hu/plain/rss.xml
$NUMITEMS - mennyi bejegyzést akarunk kilistázni
$TIMEFORMAT - a dátum milyen formában jelenjen meg.
$CACHEFILE - a letárolt tartalmat hova mentse a program (erre azért van szükség, hogy ne minden oldatelöltéskor szedjük le az RSS-t, mert az belassítaná a rendszert, hanem megadott időközönként frissítsünk csak)
$CACHETIME - milyen időközönként kapcsolódjon fel az RSS-re és szedje le az új bejegyzéseket.
Ennyit kell gyakorlatilag tudni a beállításokhoz most pedig lássuk a magát a kódot:
header('Content-Type: text/html; charset=utf-8');
# define script parameters
$FEEDURL = "http://www.sg.hu/plain/rss.xml";
$NUMITEMS = 20;
$TIMEFORMAT = "Y. F j., h:i";
$CACHEFILE = "/tmp/" . md5($FEEDURL);
$CACHETIME = 1; # hours
# download the feed iff a cached version is missing or too old
if(!file_exists($CACHEFILE) || ((time() - filemtime($CACHEFILE)) > 3600 * $CACHETIME)) {
if($feed_contents = @file_get_contents($FEEDURL)) {
# write feed contents to cache file
$fp = fopen($CACHEFILE, 'w');
fwrite($fp, $feed_contents);
fclose($fp);
}
}
include "rss.parser.php";
$rss_parser = new myRSSParser($CACHEFILE);
# read feed data from cache file
$feeddata = $rss_parser->getRawOutput();
extract($feeddata['RSS']['CHANNEL'][0], EXTR_PREFIX_ALL, 'rss');
# display leading image
if(isset($rss_IMAGE[0]) && $rss_IMAGE[0]) {
extract($rss_IMAGE[0], EXTR_PREFIX_ALL, 'img');
echo "
";
}
# display feed title
echo "";
# display feed items
$count = 0;
foreach($rss_ITEM as $itemdata) {
# article title
echo "".htmlspecialchars(stripslashes($itemdata['TITLE']))."
";
# article description
echo htmlspecialchars(stripslashes($itemdata['DESCRIPTION'])),"
\n";
# article date
echo "",date($TIMEFORMAT, strtotime($itemdata['PUBDATE'])),"
\n\n";
if(++$count >= $NUMITEMS) break;
}
A php 27. sorától kezdve lehet szépítgetni a megjelenítést. A program, ha képet tlaál az RSS-ben az automatikusan kirakja, ezen felül kiírja az RSS címét a bejegyzések címeit leírásait és dátumát is.