RSS (Rich Site Summary) è il formato più utilizzato per il "Content Syndication", ovvero per la diffusione nel WEB di news e contenuti in genere, ed è uno dei tanti "dialetti" XML. Un file RSS (o "RSS feed") contiene la descrizione dei contenuti di un sito ed è leggibile da applicazioni di vario genere, molto spesso però si tratta di altri siti che a loro volta riutilizzano questi contenuti (ad esempio per creare liste di link).
pro.html.it ha già dedicato alla storia e alla descrizione di RSS alcuni articoli (riportati più avanti al paragrafo "Conclusioni e link utili"), nelle prossime pagine daremo per scontata la conoscenza degli aspetti affrontati nell'articolo di Introduzione a RSS pertanto ne consiglio la lettura prima di proseguire.
PEAR XML_RSS
Essendo RSS un formato XML, potremmo essere portati a pensare che la lettura sia necessariamente complessa, che richieda una buona conoscenza di almeno uno dei parser XML a disposizione del programmatore PHP, e che ciò renda l'accesso a tali contenuti un'operazione non alla portata di tutti.
Fortunatamente le cose non stanno così, a patto che si decida di ricorrere a PEAR: grazie al package XML_RSS siamo in grado di prelevare da un file RSS tutte le informazioni necessarie e restituirle in un semplice array.
Il "parsing" avviene in modo del tutto trasparente all'utilizzatore, senza che questi veda neppure una riga di codice XML.
Il parser utilizzato da XML_RSS è quello built-in con Php che scorre il file un po' alla volta, non è quindi necessario caricarlo interamente in memoria: caratteristica che si dimostra particolarmente utile con feed RSS di dimensioni notevoli. In breve, stiamo parlando di un parser di tipo SAX.
Oltre all'installazione base di PEAR, XML_RSS richiede la presenza di altri due packages dai quali dipende: XML_Parser e XML_Tree. Se non è questo il vostro caso potete seguire la guida all'installazione descritta nell'PEAR: una montagna di codice PHP di freephp.html.it dedicato a PEAR.
Quali versioni di RSS?
Anche se XML_RSS ci semplifica di molto la vita non è perfetta. Se avete letto l'Introduzione a RSS su pro.html.it citato precedentemente siete a conoscenza del fatto che RSS non è uno standard ben definito, e che dietro quell'unica sigla si nascondono più formati curati da sviluppatori totalmente differenti: la versione del documento è riconoscibile, oltre che dalla sintassi, dalla dichiarazione immediatamente successiva all'intestazione XML del feed RSS.
<?xml version="1.0"?>
<rss version="0.93">
>channel>
.
.
.
Purtroppo XML_RSS nella sua attuale versione è in grado di operare soltanto con RSS 0.9x, con qualche modifica la renderemo perfettamente in grado di gestire RSS 2.0, ma purtroppo non è compatibile con RSS 1.0 la cui struttura è del tutto peculiare.
Non mi risulta che al momento esistano classi analoghe a XML_RSS compatibili con RSS 1.0, quindi prossimamente dedicheremo alla creazione di un parser RSS 1.0 compliant un articolo apposito, che ci fornirà l'occasione per affrontare nel dettaglio le funzioni XML di Php.
XML_RSS in azione
<?php
/*
Include la definizione della classe da PEAR
*/
include_once('XML/RSS.php') ;
/*
Il feed RSS da leggere, può essere sia un file locale che remoto.
*/
$target='http://pear.php.net/rss.php' ;
/*
Istanzia l'oggetto
*/
$rss = &new XML_RSS($target) ;
/*
Effettua il parsing e raccoglie le informazioni
*/
$rss->parse() ;
echo('<pre>') ;
print_r($rss->getChannelInfo()) ;
echo(</pre>') ;
?>
Tutto qui, il feed RSS è stato letto e le informazioni raccolte, l'output di print_r() è la rappresentazione in stringa di un array PHP contenente le informazioni sul <channel> PEAR.
Array
(
[title] => PEAR
[link] => http://pear.php.net/
[description] => This is a list containing the latest releases from PEAR.
)
Se desideriamo leggere un documento remoto XML_RSS richiede che nel php.ini la direttiva allow_url_fopen sia On.
Metodi che restituiscono i dati
Gli elementi fondamentali di un documento RSS sono 4, per ognuno di essi XML_RSS mette a disposizione un metodo:
- XML_RSS::getChannelInfo() fornisce le informazioni relative all'elemento <channel>, tipicamente meta dati relativi al canale descritto dal documento RSS: titolo, url e una breve descrizione.
- XML_RSS::getItems() restituisce un array con i dati dei vari <item>, che sono l'elemento più importante di un documento RSS.
- XML_RSS::getImages() ricava i dati degli elementi <image>, ad esempio un logo che potremmo voler inserire anche nelle pagine che utilizzano le informazioni recuperate dal file RSS.
- XML_RSS::getTextinputs(), analogamente a quanto avviene per l'elemento <image> se il documento RSS presenta un elemento <textinput> è possibile inserire nelle nostre pagine un form (che consenta, ad esmpio, di effettuare ricerche nel canale descritto).
A questi si aggiunge XML_RSS::getStructure() che fornisce tutti gli elementi del documento RSS in un unico array.
Per una descrizione più dettagliata invito a fare riferimento alla documentazione di PEAR che per una volta è molto chiara, è il momento di passare alla pratica.
Compatibilità con RSS 2.0
Nell'esempio precedente è andato tutto bene perchè la versione RSS utilizzata da PEAR è 0.93, ma se avessimo voluto leggere ad esempio il feed di webnews.html.it che utilizza il formato 2.0? Avremmo ottenuto dei dati piuttosto incompleti....
L'autore di XML_RSS non ha ancora adeguato la propria classe ma uno dei vantaggi della programmazione object oriented è, entro certi limiti, l'estendibilità e l'adattabilità del codice.
Ecco quindi come possiamo adattare XML_RSS senza modificarne direttamente il sorgente.
<?php
/*** File "XML_RSS_EXTENSION.php" ***/
include_once('XML/RSS.php') ;
class XML_RSS_ext20 extends XML_RSS{
function XML_RSS_ext20($target){
$this->XML_RSS($target) ;
$this->_extendChannel() ;
$this->_extendItem() ;
$this->_extendImage() ;
$this->_extendModules() ;
}
/*
Aggiunge i nuovi sotto-elementi a <channel>
*/
function _extendChannel(){
$cTags20 = array( 'LANGUAGE', 'COPYRIGHT', 'MANAGINGEDITOR', 'WEBMASTER', 'PUBDATE',
'LASTBUILDDATE', 'CATEGORY', 'GENERATOR', 'DOCS', 'CLOUD', 'TTL', 'RATING',
'SKIPHOURS', 'SKIPDAYS') ;
$this->channelTags = array_merge($this->channelTags, $cTags20) ;
}
/*
Aggiunge i nuovi sotto-elementi a <item>
*/
function _extendItem(){
$iTags20 = array( 'AUTHOR', 'CATEGORY', 'COMMENTS', 'ENCLOSURE',
'GUID', 'PUBDATE', 'SOURCE') ;
$this->itemTags = array_merge($this->itemTags, $iTags20) ;
}
/*
Aggiunge i nuovi sotto-elementi a <image>
*/
function _extendImage(){
$img20 = array('WIDTH', 'HEIGHT') ;
$this->imageTags = array_merge($this->imageTags, $img20) ;
}
/*
Rende il parser compatibile con alcuni moduli di estensione
*/
function _extendModules(){
$modExt= array('BLOGCHANNEL:BLINK', 'SY:UPDATEPERIOD', 'SY:UPDATEFREQUENCY', 'SY:UPDATEBASE') ;
$this->moduleTags = array_merge($this->moduleTags, $modExt) ;
}
}// END class
?>
Non ci soffermeremo su cosa faccia esattamente questa estensione, invito i più curiosi ad esaminare il sorgente originale di XML_RSS e le specifiche RSS 2.0.
Catturare le news di HTML.it
Dopo le modifiche appena apportate siamo pronti per inserire le webnews di HTML.it nelle nostre pagine, il feed RSS è reperibile dall'homepage di Webnews.
<?php
include_once('XML_RSS_EXTENSION.php') ;
$webNews=&new XML_RSS_ext20('https://www.html.it/news.xml') ;
$webNews->parse() or die('Lettura impossibile') ;
$channel= $webNews->getChannelInfo() ;
$news= $webNews->getItems() ;
$logo= $webNews->getImages() ;
/*
$webNews->getImages() restituisce un array moultidimensionale di tutte le immagini presenti e dei rispettivi dati, nel nostro caso esiste una sola immagine.
*/
$logo= $logo[0] ;
$output = '' ;
$output = '<img src="'.$logo['url'].'" alt="'.$logo['title'].'" width="'.$logo['width'].'" height="'.$logo['height'].'" />' ;
$output .= '<h1 style="margin-bottom: 0 ; font-size: 14pt">'.$channel['title'].'</h1>'.$channel['link'].'<br>' ;
$output .= '<h2 style="margin-top: 10px ; margin-bottom: 0 ; font-size: 13pt">'.$channel['description'].'</h2>' ;
$output.= 'Aggiornato il '.date('d.m.Y alle ore H:i', strtotime($channel['pubdate'])).'<br><br>' ;
/*
Scorriamo le news
*/
foreach($news as $n ){
$output.= "- <a href="{$n['link']}" target="_blank">{$n['title']}</a><br />" ;
$output.=$n['description'].'<br /><br />' ;
}
echo($output) ;
?>
Ecco l'ouput che otterremo, di certo non si tratta di una grafica accattivante ma rende l'idea di come si possono manipolare i dati prelevati.