6.Le langage PHP
6.17.Parser un document XML
6.17.2.Parseur de type "SAX parser"
6.17.2.3.Amélioration avec xml_set_character_data_handler() et xml_set_element_handler()
Pour savoir si le texte rencontré est lié à une balise <item> ou <link> il faut se servir de la détection par le "parseur" des balises ouvrantes (et éventuellement fermantes).
Pour cela, nous devons donc créer une fonction chargée de traiter le cas des balises ouvrantes. Celle-ci sera appelée par le "parseur" avec trois paramètres: l'identifiant du parseur, le nom de la balise ouvrante rencontrée et le tableau des attributs de la balise. Cette fonction doit être déclarée auprès du "parseur" à l'aide de la fonction xml_set_element_handler() qui attend 3 paramètres: l'identifiant du parseur, le nom de la fonction traitant les balises ouvrantes et le nom de la fonction traitant les balises fermantes. La fonction en charge des balises fermantes est quant à elle appelée avec deux paramètres: l'identifiant du parseur et le nom de la balise fermante rencontrée.
Notre script peut donc être amélioré de la manière suivante:
<?php
$fichier = "http://www.phpfacile.com/exemples_live/fluxrss.rss";
// Ma propre fonction de traitement des balises ouvrantes
function fonctionBaliseOuvrante($parseur, $nomBalise, $tableauAttributs)
{
// En fait... nous nous conteterons de mémoriser le nom de la balise
// afin d'en tenir compte dans la fonction "fonctionTexte"
global $derniereBaliseRencontree;
$derniereBaliseRencontree = $nomBalise;
}
// Ma propre fonction de traitement des balises fermantes
function fonctionBaliseFermante($parseur, $nomBalise)
{
// On oublie la dernière balise rencontrée
global $derniereBaliseRencontree;
$derniereBaliseRencontree = "";
}
// Ma propre fonction de traitement du texte
// qui est appelée par le "parseur"
function fonctionTexte($parseur, $texte)
{
global $derniereBaliseRencontree;
// Selon les cas, nous affichons le texte
// ou nous proposons un lien
// ATTENTION: Par défaut les noms des balises sont
// mises en majuscules
switch ($derniereBaliseRencontree) {
case "TITLE":
echo $texte;
break;
case "LINK":
echo ":<a href=\"$texte\">L'article complet</a><br />";
break;
}
}
// Création du parseur XML
$parseurXML = xml_parser_create();
// Je précise le nom des fonctions à appeler
// lorsque des balises ouvrantes ou fermantes sont rencontrées
xml_set_element_handler($parseurXML, "fonctionBaliseOuvrante"
, "fonctionBaliseFermante");
// Je précise le nom de la fonction à appeler
// lorsque du texte est rencontré
xml_set_character_data_handler($parseurXML, "fonctionTexte");
// Ouverture du fichier
$fp = fopen($fichier, "r");
if (!$fp) die("Impossible d'ouvrir le fichier XML");
// Lecture ligne par ligne
while ( $ligneXML = fgets($fp, 1024)) {
// Analyse de la ligne
// REM: feof($fp) retourne TRUE s'il s'agit de la dernière
// ligne du fichier.
xml_parse($parseurXML, $ligneXML, feof($fp)) or
die("Erreur XML");
}
xml_parser_free($parseurXML);
fclose($fp);
?>
Voilà, nous ne sommes vraiment pas loin de la solution. Reste qu'il serait bon de distinguer le lien vers le site, des liens vers les articles et pourquoi ne pas plutot mettre les liens directement sur les titres plutôt qu'à coté.
6.17.2.4.Le "parseur" complet
Et bien, en fait, dans ce chapitre, vous n'apprendrez rien de nouveau (en tout cas, pas de nouvelles fonctions). Pour parvenir à nos besoins, ils suffit de bien analyser le problème, voir ce dont on dispose et ce dont on a besoin. En l'occurence, ici, nous ne connaissons le lien associé à un article qu'après en avoir eu le titre ce qui ne nous permet pas d'afficher les éléments au fur et à mesure dans le cas où l'on souhaite créer des liens du type <a href="lien">titre</a> il faut donc mémoriser les informations avant de les afficher et savoir quand les afficher.
Notre script complet devient alors:
<?php
$fichier = "http://www.phpfacile.com/exemples_live/fluxrss.rss";
// Ma propre fonction de traitement des balises ouvrantes
function fonctionBaliseOuvrante($parseur, $nomBalise, $tableauAttributs)
{
// En fait... nous nous conteterons de mémoriser le nom de la balise
// afin d'en tenir compte dans la fonction "fonctionTexte"
global $derniereBaliseRencontree;
$derniereBaliseRencontree = $nomBalise;
}
// Ma propre fonction de traitement des balises fermantes
function fonctionBaliseFermante($parseur, $nomBalise)
{
global $derniereBaliseRencontree;
global $titre;
global $lien;
switch ($nomBalise) {
case "CHANNEL" :
// nous quittons le bloc channel
// nous pouvons afficher le titre de notre
// liste de d'articles
echo "<center><b>Les dernieres nouvelles issues de ".
"<a href=\"$lien\">$titre</a></b></center>";
// Et on oublie
$titre = "";
$lien = "";
break;
case "ITEM" :
// nous quittons un bloc item
// nous pouvons afficher le titre de l'article
echo "- <a href=\"$lien\">$titre</a><br />";
// et on oublie
$titre = "";
$lien = "";
break;
}
// On oublie la dernière balise rencontrée
// et tout le reste
$derniereBaliseRencontree = "";
}
// Ma propre fonction de traitement du texte
// qui est appelée par le "parseur"
function fonctionTexte($parseur, $texte)
{
global $derniereBaliseRencontree;
global $titre;
global $lien;
// Nous n'affichons pas le texte ou lien directement
// nous attendrons de rencontrer la balise fermante
// et ainsi d'avoir tous les éléments avant l'affichage.
// ATTENTION: Par défaut les noms des balises sont
// mises en majuscules
switch ($derniereBaliseRencontree) {
case "TITLE":
$titre = $texte;
break;
case "LINK":
$lien = $texte;
break;
}
}
// Création du parseur XML
$parseurXML = xml_parser_create();
// Je précise le nom des fonctions à appeler
// lorsque des balises ouvrantes ou fermantes sont rencontrées
xml_set_element_handler($parseurXML, "fonctionBaliseOuvrante"
, "fonctionBaliseFermante");
// Je précise le nom de la fonction à appeler
// lorsque du texte est rencontré
xml_set_character_data_handler($parseurXML, "fonctionTexte");
// Ouverture du fichier
$fp = fopen($fichier, "r");
if (!$fp) die("Impossible d'ouvrir le fichier XML");
// Lecture ligne par ligne
while ( $ligneXML = fgets($fp, 1024)) {
// Analyse de la ligne
// REM: feof($fp) retourne TRUE s'il s'agit de la dernière
// ligne du fichier.
xml_parse($parseurXML, $ligneXML, feof($fp)) or
die("Erreur XML");
}
xml_parser_free($parseurXML);
fclose($fp);
?>
Et voilà!