Afficher un flux RSS avec SimpleXml

Afficher un flux RSS avec SimpleXml

Difficulté

php xmljavascript htmlcss

Un flux RSS est un document de format xml qui contient des balises normalisées contenant le titre, le lien vers l’actualité et la description de l’actualité.

Nous avons déjà vu comment afficher un flux avec la librairie Dom de php5.

Aujourd’hui, nous allons utiliser la librairie simplexml, incluse également par défaut à php5.
Comme son nom l’indique, cette librairie est simple d’utilisation pour tout habitué des tableaux associatifs multidimensionnels.

J’ai choisi d’afficher le flux de ce site, avec une petite « bulle » affichant le début de la description de l’actu.
Voici le résultat (on passe sa souris sur les liens pour voir la bulle apparaître !):

1. La classe Simplexml de php 5

A noter : Avant php 5.1.2, cette librairie est incluse mais n’est pas activée par défaut.

Le chargement d’un document est très simple :

Une simple fonction nous crée directement un objet SimpleXml

$xml = simplexml_load_file('http://www.unpointvirgule.fr/feed/');

Voilà donc notre flux chargé. L’objet SimpleXml exclut l’élément racine. Autrement dit, nous sommes DANS l’élément racine.
On crée ensuite la variable pour stocker les données dans un tableau.

$html_tab = array();

2. La stucture du flux

Sans vouloir expliciter la structure d’un document rss (qui est un document xml normalisé), voici le contenu de notre flux (volontairement simplifié) :

<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>unPointVirgule</title>
	<atom:link href="http://www.unpointvirgule.fr/feed/" rel="self" type="application/rss+xml" />
	<link>http://unpointvirgule.fr</link>
	<language>fr-FR</language>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<item>
			<title>Jquery vs mootools pour un effet « fancy » sous vos menus</title>
			<link>http://unpointvirgule.fr/2012/03/jquery-vs-mootools-pour-un-effet-fancy-sous-vos-menus/</link>
			<comments>http://unpointvirgule.fr/2012/03/jquery-vs-mootools-pour-un-effet-fancy-sous-vos-menus/#comments</comments>
			<pubDate>Thu, 01 Mar 2012 19:38:57 +0000</pubDate>
			<dc:creator>p'tite virgule</dc:creator>
					<category><![CDATA[JQuery, mootols, etc...]]></category>

			<guid isPermaLink="false">http://unpointvirgule.fr/?p=59</guid>
			<description><![CDATA[Avec le développement des bibliothèques de script pour Javascript, il devient difficile de choisir l’utilisation de l’une ou l’autre. Aujourd’hui, je me suis penchée sur Mootools, que vous pouvez télécharger ici. J’ai appris à coder directement à l’aide des fonctions … <a href="http://unpointvirgule.fr/2012/03/jquery-vs-mootools-pour-un-effet-fancy-sous-vos-menus/" class="excerpt-more-link">Lire la suite... <span class="meta-nav">→</span></a>]]></description>
			<wfw:commentRss>http://unpointvirgule.fr/2012/03/jquery-vs-mootools-pour-un-effet-fancy-sous-vos-menus/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		</item>
		<item>
			<title>De l’utilité sémantique des tableaux html…</title>
			<link>http://unpointvirgule.fr/2012/01/de-lutilite-des-tableaux-valides/</link>
			<comments>http://unpointvirgule.fr/2012/01/de-lutilite-des-tableaux-valides/#comments</comments>
			<pubDate>Sun, 15 Jan 2012 15:16:14 +0000</pubDate>
			<dc:creator>p'tite virgule</dc:creator>
					<category><![CDATA[Webdesign]]></category>
			<category><![CDATA[Xhtml html5...]]></category>

			<guid isPermaLink="false">http://unpointvirgule.fr/?p=8</guid>
			<description><![CDATA[« Les tableaux doivent être bannis ! » On nous le dit depuis le développement du web dit « sémantique » : les tableaux doivent être bannis dans la construction des sites…. Alors on n’en parle plus… Et on ne fait plus de tableaux. … <a href="http://unpointvirgule.fr/2012/01/de-lutilite-des-tableaux-valides/" class="excerpt-more-link">Lire la suite... <span class="meta-nav">→</span></a>]]></description>
			<wfw:commentRss>http://unpointvirgule.fr/2012/01/de-lutilite-des-tableaux-valides/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

On souhaite accéder aux éléments enfants de item

3. La navigation dans le flux

La spécificité par rapport à la classe Dom est que nous pouvons naviguer à l’intérieur un peu comme à travers un tableau php classique.
Pour afficher simplement le contenu du flux chargé, on utilisera print_r($xml) encadré de la balise <pre>
qui nous affichera :

SimpleXMLElement Object
(
    [@attributes] => Array
        (
            [version] => 2.0
        )

    [channel] => SimpleXMLElement Object
        (
            [title] => unPointVirgule
            [link] => http://unpointvirgule.fr
            [description] => SimpleXMLElement Object
                (
                )

            [lastBuildDate] => Sat, 25 May 2013 08:54:39 +0000
            [language] => fr-FR
            [generator] => http://wordpress.org/?v=3.5.1
            [item] => Array
                (                   
										[0] => SimpleXMLElement Object
                        (
                            [title] => Jquery vs mootools pour un effet « fancy » sous vos menus
                            [link] => http://unpointvirgule.fr/2012/03/jquery-vs-mootools-pour-un-effet-fancy-sous-vos-menus/
                            [comments] => http://unpointvirgule.fr/2012/03/jquery-vs-mootools-pour-un-effet-fancy-sous-vos-menus/#comments
                            [pubDate] => Thu, 01 Mar 2012 19:38:57 +0000
                            [category] => SimpleXMLElement Object
                                (
                                )

                            [guid] => http://unpointvirgule.fr/?p=59
                            [description] => SimpleXMLElement Object
                                (
                                )

                        )

                    [1] => SimpleXMLElement Object
                        (
                            [title] => De l’utilité sémantique des tableaux html…
                            [link] => http://unpointvirgule.fr/2012/01/de-lutilite-des-tableaux-valides/
                            [comments] => http://unpointvirgule.fr/2012/01/de-lutilite-des-tableaux-valides/#comments
                            [pubDate] => Sun, 15 Jan 2012 15:16:14 +0000
                            [category] => Array
                                (
                                    [0] => SimpleXMLElement Object
                                        (
                                        )

                                    [1] => SimpleXMLElement Object
                                        (
                                        )

                                )

                            [guid] => http://unpointvirgule.fr/?p=8
                            [description] => SimpleXMLElement Object
                                (
                                )

                        )

                )

        )

)

Pour récupérer la description du premier item du flux, nous utiliserons donc : $xml->channel[0]->item[0]->description Cependant, nous ne pourrons pas pointer directement sur les éléments item. En effet, il n’y pas pas d’équivalent à la méthode du DomDocument getElementsByTagName. Nous allons donc pointer les éléments item de la façon suivante :

 $liste = $xml->channel[0];

Nous avons donc la liste des enfants directs de channel, entre autres donc les fameux item. On voit bien ici que nous devons connaître la structure complète du document pour pouvoir accéder à l’élément qui nous intéresse. C’est la raison pour laquelle nous ne traiterons ici que les flux Rss et non pas Atom qui ont une structure différente. On peut donc maintenant effectuer l’itération pour stocker les valeurs dans notre tableau. On décide de n’afficher que les 5 actualités, les plus récentes, donc les 5 premières de la liste.


for($i=0;$i<5;$i++){
 $item = $liste->item[$i];
 $html_tab[$i]['id']=$id;
 //date
 $laDate=$item->pubDate;
 $affich_date = date('d-m-Y', strtotime($laDate));
 $html_tab[$i]['date']=$affich_date;
 //description
 $description_tot=$item->description;
 $description_tot = strip_tags($description_tot);
 $description_tot = htmlspecialchars($description_tot);
 $description_tot = addslashes($description_tot);
 $description = $description_tot;
 $description = substr($description_tot,0,200);
 $der_espace = strrpos($description, " ");
 $description = substr($description,0,$der_espace);
 $description=str_replace(CHR(10),"",$description); //pour effacer les retour chariot du fichier rss
 $description=str_replace(CHR(39),''',$description);//pour convertir les simples quotes
 $description=str_replace(CHR(34),'"',$description);//pour convertir les doubles quotes
 if (strlen($description) < strlen($description_tot)) $description .= '...'; $html_tab[$i]['description']=$description; //lien $html_tab[$i]['lien']=$item->link;
 //titre
 $html_tab[$i]['titre']=$item->title;
 $id++;
}

Pour chaque noeud enfant de item qui nous intéressent (title, link, description, pubdate), on récupère sa valeur textuelle directement.

4. Le stockage des éléments dans une variable php

Pour chaque actualité, on affichera la date, le lien avec le titre de l’actualité, et on appelle une fonction javascript au survol (hover) du lien pour afficher la bulle contenant la description.

Il va donc falloir passer comme argument à cette fonction le contenu de cette description. Il doit donc être exempt de balises html, de retour chariot et de quotes.

Ces traitements devraient également être faits pour les autres données, ne serait-ce que pour éviter les injections xss, je ne l’ai pas fait ci dans un souci de lisibilité du code…

De plus, on n’affichera que les 200 premiers caractères dans la bulle, et ce, sans couper un mot au milieu…

Voici donc le détail des traitements effectués sur cette chaine de caractères:
- On enlève les balises html avec strip_tag,
- On convertit les caractères spéciaux avec htmlspecialchars,
- On protège les quotes et doubles quotes avec addslashes
- Mais comme cela ne suffit pas (la chaîne de caractères passées à javascript ne doit contenir aucun caractère qui gêne), nous allons convertir les simples et doubles quotes avec leur symbole numérique respectif ‘ et  »
Javascript n’y verra que du feu et le navigateur nous affichera les bons caractères.
- Il faut également supprimer les retours chariots du flux qui provoqueraient un retour à la ligne dans l’appel de la fonction. Il s’agit du caractère ASCII 10.
- On ne garde que les 200 premiers caractères en coupant la chaine avec substr,
- On cherche également le dernier espace de la chaine de caractère avec strrpos pour éviter de couper un mot au milieu,
- Et on ajoute « … » si la description n’est pas entière.

5. L’affichage en html/css

On va ensuite afficher les données du flux dans la page html – encodée bien sur en utf-8 ! ;)

<ul id="rss">
<?php
foreach($html_tab as $item){
	 //ecriture du code html avec l'appel à la fonction js popup pour la bulle
?>	 

		<li>
			<span class="date">
				<?php echo $item['date']; ?>
			</span>
			<a id="id<?php echo $item['id']; ?>" class="bulle" href="<?php echo $item['lien']; ?>" target="_blank" onmouseover="popup('id<?php echo $item['id']; ?>','<?php echo $item['description']; ?>','pop')" onmouseout="cachePop('id<?php echo $item['id']; ?>')">
				<?php echo $item['titre']; ?>
			</a>
		</li>

<?php					
}
?>
</ul>

La liste des actualités est affichée avec une liste html, mise en forme par les css suivant :

<style type="text/css">
<!--
#rss{
	border:1px solid #000;
	background-color:#c1b3f5;
	padding:10px;
	width:400px;
	line-height:15px;
	border-radius: 5px 5px 5px 5px;
	box-shadow: 0 0 10px rgba(0, 0, 0, 0.4) inset;
}
#rss li{
	clear:both;
	padding:0;
	margin-bottom:5px;
	list-style-type:none;
}
.date{
	font-size:0.8em; 
	font-style:italic; 
	color:#616161;
	padding:0 10px 5px 0;
	float:left;
}

/*bulle et popup*/
.bulle{
	position:relative;
	font-family : Georgia, Cambria, serif;
	font-size:14px;
	color:#000;
	text-decoration:none;
}
a.bulle:hover {
	background: none; /* correction d'un bug IE */
	z-index: 999;/*pour que la bulle s'affiche au dessus des autres */
	color:#ad231f;
}
.pop {
	font-family : Georgia, Cambria, serif;
	font-size:12px;
	background-color:#545454;
	padding:10px;
	position:absolute;
	width:250px;
	border:1px solid #000;
	border-radius: 5px 5px 5px 5px;
	box-shadow: 0 0 10px rgba(0, 0, 0, 0.4) inset;
	color:#FFFFFF;
	text-decoration:none;
	text-align:justify;
	width:350;
	top:30px;
	left:10px;
}
-->
</style>

La classe pop est positionnée en absolute, et sur le hover du lien, on ajoute un z-index pour être sûr que la bulle s’affiche au dessus des autres éléments.
J’ajoute quelques effets de bords arrondis et d’ombrage interne avec les propriétés des CSS3.

6. L’affichage de la bulle par le DOM de javascript

Et bien sur, l’affichage de la fameuse bulle pop par le dom de javascript :

<script type="text/javascript">

// <![CDATA[
//fct pour le onmouseover: apparition de la bulle
function popup(noeud,mes,classe){
		//nouveau noeud
		newElement=document.createElement("span");
		//crea du noeud texte avec un innerhtml pour permettre l'interpetation des balises html
		newElement.innerHTML=mes;
		//attachement du nouveau noeud au noeud parent
		document.getElementById(noeud).appendChild(newElement);
		//la classe	
		newElement.className=classe;
}

//fct pour le onmouseout: suppresion de la bulle en effaçant le noeud correspondant
function cachePop(noeud){
	leNoeud=document.getElementById(noeud);
	leNoeud.removeChild(leNoeud.childNodes[1]);
}
    // ]]>
</script>

On crée un élément span d’une classe passée en argument dans lequel on greffe le texte de la description de l’actualité.
Ce qui permet d’affecter différentes classes à la bulle par exemple.
Ce span doit disparaître lorsqu’on quitte le lien, donc au mouseout, ce que fait la fonction cache pop.

7. La fonction xpath

Je n’ai volontairement pas parlé de la fonction xpath pour que cet article soit vraiment le pendant de celui utilisant le dom pour afficher le flux, mais SimpleXml possède une méthode pour utiliser directement Xpath un langage de requête universel basé sur la structure spécifique du xml et plus généralement de tout document balisé.

Nous aurions pu donc cibler directement les éléments item dont nous avons besoin, et uniquement les 5 premiers par [position()>0][position()<=6] : du premier au sixième élément de la liste.

$xml->xpath('//item[position()>0][position()<=6]')

On voit donc que même si l’objet SimpleXml a une syntaxe plus accessible, il est plus limité même si la fonction xpath permet de contourner parfois ce problème sur des documents xml complexes.

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Vous pouvez utiliser ces balises et attributs HTML : <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>