web-dev-qa-db-fra.com

Utilisation de SimpleXML pour lire le flux RSS

J'utilise PHP et simpleXML pour lire le flux rss suivant:

http://feeds.bbci.co.uk/news/england/rss.xml

Je peux obtenir la plupart des informations que je veux ainsi:

$rss = simplexml_load_file('http://feeds.bbci.co.uk/news/england/rss.xml');

echo '<h1>'. $rss->channel->title . '</h1>';

foreach ($rss->channel->item as $item) {
   echo '<h2><a href="'. $item->link .'">' . $item->title . "</a></h2>";
   echo "<p>" . $item->pubDate . "</p>";
   echo "<p>" . $item->description . "</p>";
} 

Mais comment pourrais-je sortir l'image miniature qui est dans la balise suivante:

<media:thumbnail width="66" height="49" url="http://news.bbcimg.co.uk/media/images/51078000/jpg/_51078953_226alanpotbury.jpg"/>  
20
geoffs3310

SimpleXML est assez mauvais pour gérer les espaces de noms. Vous avez deux choix: le hack le plus simple consiste à simplement lire le contenu du flux dans une chaîne et à remplacer les espaces de noms;

$feed = file_get_contents('http://feeds.bbci.co.uk/news/england/rss.xml');
$feed = str_replace('<media:', '<', $feed);

$rss = simplexml_load_string($feed);
...

Vous pouvez maintenant accéder directement à l'élément thumbnail.

La méthode la plus élégante (pas vraiment) consiste à découvrir l'URI utilisé par l'espace de noms. Si vous regardez le code source de http://feeds.bbci.co.uk/news/england/rss.xml vous voyez qu'il pointe vers http://search.yahoo.com/mrss/.

Vous pouvez maintenant utiliser cet URI dans la méthode children() d'un SimpleXMLElement pour obtenir le contenu de l'élément media: thumbnail;

$rss = simplexml_load_file('http://feeds.bbci.co.uk/news/england/rss.xml');

foreach ($rss->channel->item as $item) {
    $media = $item->children('http://search.yahoo.com/mrss/');
    ...
}
5
Björn

Comme vous le savez déjà, SimpleXML vous permet de sélectionner l'enfant d'un nœud en utilisant l'opérateur de propriété d'objet -> Ou l'attribut d'un nœud en utilisant l'accès au tableau ['name']. C'est super, mais l'opération ne fonctionne que si ce que vous sélectionnez appartient au même espace de noms .

Si vous voulez "hop" d'un espace de noms à un autre, vous pouvez utiliser children() ou attributes() méthodes. Dans votre cas, cela est rendu un peu plus délicat car vous avez <item/> Dans l'espace de noms global, le nœud que vous recherchez se trouve dans l'espace de noms "media" *, puis les attributs sont à nouveau dans l'espace de noms global ( ils ne sont pas préfixés.) Donc, en utilisant la notation normale objet/tableau, vous devrez "hop" deux fois:

foreach ($rss->channel->item as $item)
{
    // we load the attributes into $thumbAttr
    // you can either use the namespace prefix
    $thumbAttr = $item->children('media', true)->thumbnail->attributes();

    // or preferably the namespace name, read note below for an explanation
    $thumbAttr = $item->children('http://search.yahoo.com/mrss/')->thumbnail->attributes();

    echo $thumbAttr['url'];
}

*Remarque

Je me réfère à l'espace de noms comme l'espace de noms "media" mais ce n'est pas vraiment correct. Le nom de l'espace de noms est http://search.yahoo.com/mrss/, Et "media" n'est qu'un préfixe, une sorte d'alias si vous voulez. Ce qui est important à garder à l'esprit est que http://search.yahoo.com/mrss/ Est le vrai nom de l'espace de noms. À un moment donné, votre fournisseur RSS pourrait décider de changer le préfixe en, par exemple, "yahoo" et votre script cessera de fonctionner si votre script fait référence au préfixe "media". Cependant, si vous utilisez le nom de l'espace de noms, il continuera de fonctionner quel que soit le préfixe.

19
Josh Davis