RSS olvasó és megjelenítő PHP script

A legújabb írásunkban egy RSS 2.0 kiolvasót mutatunk be nektek, amellyel akár saját honlapotokra készíthettek más oldalakról átszívott hírekkel teli blokkot. Lássunk tehát hozzá.
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 .= "

"; if($LINK) $this->retval .= ""; $this->retval .= stripslashes($TITLE); if($LINK) $this->retval .= ""; $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 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 "

".htmlspecialchars($rss_TITLE)."

"; # 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.

RSS olvasó és megjelenítő PHP script

#totalstudio