使用 SimpleXML 读取 RSS 提要

Posted

技术标签:

【中文标题】使用 SimpleXML 读取 RSS 提要【英文标题】:Using SimpleXML to read RSS feed 【发布时间】:2011-06-20 17:07:18 【问题描述】:

我正在使用 php 和 simpleXML 来阅读以下 rss 提要:

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

我可以像这样获得大部分我想要的信息:

$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>";
 

但是我将如何输出以下标签中的缩略图:

<media:thumbnail   url="http://news.bbcimg.co.uk/media/images/51078000/jpg/_51078953_226alanpotbury.jpg"/>  

【问题讨论】:

【参考方案1】:

如您所知,SimpleXML 允许您使用对象属性运算符-&gt; 选择节点的子节点,或者使用数组访问['name'] 选择节点的属性。这很好,但只有当您选择的内容属于同一个命名空间时,该操作才有效。

如果您想“跳跃” 从一个命名空间到另一个命名空间,您可以使用children()attributes() 方法。在您的情况下,这有点棘手,因为您在全局命名空间中有&lt;item/&gt;,您要查找的节点在“媒体”命名空间*中,然后属性再次在全局命名空间中(它们不是前缀。)因此,使用普通的对象/数组表示法,您必须 "hop" 两次:

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'];


*注意

我将命名空间称为“媒体”命名空间,但这并不完全正确。命名空间名称是http://search.yahoo.com/mrss/,“media”只是一个前缀,如果你愿意的话,是某种别名。重要的是要记住http://search.yahoo.com/mrss/ 是命名空间的真实名称。在某些时候,您的 RSS 提供商可能决定将前缀更改为“yahoo”,如果您的脚本引用“媒体”前缀,您的脚本将停止工作。但是,如果您使用命名空间名称,无论前缀如何,它都会继续工作。

【讨论】:

您指定的脚本是读取xml并将其放入我们网站的方式。如果假设我只有在 RSS 提要(xml 内容)发生变化时才触发此脚本来读取 xml,该怎么做? 这与XML无关,请将其作为新问题发布,以便正确回答。【参考方案2】:

SimpleXML 在处理命名空间方面非常糟糕。您有两个选择:最简单的 hack 是简单地将提要的内容读入字符串并替换命名空间;

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

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

现在您可以直接访问元素thumbnail

更优雅(不是真的)方法是找出命名空间使用的 URI。如果您查看http://feeds.bbci.co.uk/news/england/rss.xml 的源代码,您会发现它指向http://search.yahoo.com/mrss/

现在您可以在 SimpleXMLElement 的 children() 方法中使用此 URI 来获取 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/');
    ...

【讨论】:

-1 与内置命名空间处理相比,建议将天真的字符串操作作为任何类型的选项。不知道为什么您认为 children 方法“非常糟糕”和“不优雅” - 您必须告诉 SimpleXML somewhere 您想要哪个命名空间;您甚至可以(从 PHP 5.3 起)使用 XML 前缀 (-&gt;children('media', true)),尽管如果 XML 的生成方式稍有不同,URI 是唯一保证不会更改的标识符。 这不是最好的主意(请参阅上面的 IMSoP 评论),但由于这是公认的答案,因此这是正确的方法:str_replace(array('&lt;media:', '&lt;/media:'), array('&lt;', '&lt;/'), $feed); @sun:也好不了多少。它会破裂。这甚至不做任何 bare 标签解析。

以上是关于使用 SimpleXML 读取 RSS 提要的主要内容,如果未能解决你的问题,请参考以下文章

生成 PHP SimpleXML RSS 提要时出现 UTF8 错误

如何从 php 中的 rss 提要获取图像

PHP SimpleXML:提要修改

解析 XML(RSS 提要)的 PHP 错误

用于读取 RSS 和 ATOM 提要的 java 库 [重复]

使用Spring启动的RSS提要