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 comme suit:

$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 afficherais-Je l'image de la vignette 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"/>  
17
demandé sur Joel Christophel 2011-02-03 17:22:57

2 réponses

SimpleXML est assez mauvais pour gérer les espaces de noms. Vous avez deux choix: le hack le plus simple est de 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);
...

Maintenant vous pouvez accéder à l'élément thumbnail directement.

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

Maintenant vous pouvez utiliser cette URI dans le children() méthode de SimpleXMLElement pour obtenir le contenu du média:vignette de l'élément;

$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/');
    ...
}
3
répondu Björn 2011-02-03 14:31:03

comme vous le savez déjà, SimpleXML vous permet de sélectionner l'enfant d'un noeud en utilisant l'opérateur de propriété de l'objet -> ou l'attribut d'un noeud en utilisant l'accès au tableau ['name']. C'est génial, mais l'opération ne fonctionne que si vous choisissez de le appartient pour le même espace de noms.

Si vous voulez "hop" d'un namespace à un autre, vous pouvez utiliser le children() ou attributes() méthodes. Dans votre cas, cela est un peu plus compliqué parce que vous avez <item/> dans le namespace global, le noeud que vous recherchez est dans le namespace "media"* et les attributs sont à nouveau dans le namespace global (ils ne sont pas préfixés).) Ainsi, 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'];
}

* Note

je me réfère à l'espace de noms comme l'espace de noms "media" mais ce n'est pas vraiment correct. Le nom du namespace est http://search.yahoo.com/mrss/, et "médias" est un préfixe, une sorte de alias si vous voulez. Ce qui est important de 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, disons, "yahoo" et votre script cessera de fonctionner si votre script se réfère au préfixe "media". Toutefois, si vous utilisez le nom d'espace de noms, il continuera à travailler peu importe le préfixe.

19
répondu Josh Davis 2011-02-04 04:48:57