Search code examples
phpzend-frameworkzend-feed

RSS Namespaces using Zend_Feed_Reader


I'm having some problems with parsing RSS feeds with Zend_Feed_Reader, specifically when a RSS namespace is being used.

The feed I'm trying to parse is the BBC News feed (http://feeds.bbci.co.uk/news/rss.xml) which includes the following:

<item>
<media:thumbnail width="66" height="49" url="http://news.bbcimg.co.uk/media/images/55800000/jpg/_55800088_013076641-1.jpg"/>
<media:thumbnail width="144" height="81" url="http://news.bbcimg.co.uk/media/images/55807000/jpg/_55807247_013074606-1.jpg"/> 
</item>

The code I'm using to parse the other items in <item> is as such:

$feed = Zend_Feed_Reader::import('http://feeds.bbci.co.uk/news/rss.xml');
foreach($feed as $item)
{
    echo $item->getTitle();
    echo $item->getDescription();
    // etc
}

However, using $item->getMedia(), $item->getMedia('thumbnail'), $item->{'media:thumbnail'} or $item->{'media:thumbnail'}() doesn't work.

I also tried writing my own extension (using this as a guide):

class Zend_Feed_Reader_Extension_Media_Entry extends Zend_Feed_Reader_Extension_EntryAbstract
{
    public function getThumbnail()
    {
        if(isset($this->_data['thumbnail']))
            return $this->_data['thumbnail'];

        $thumbnail = $this->_xpath->evaluate(
            'string(' . $this->getXpathPrefix() . '/media:thumbnail)'
        );

        if(!$thumbnail)
            $thumbnail = null;

        $this->_data['thumbnail'] = $thumbnail;

        return $this->_data['thumbnail'];
    }

    protected function _registerNamespaces()
    {
        $this->_xpath->registerNamespace('media', 'http://search.yahoo.com/mrss');
    }
}

And then doing all the appropriate extension registering (Zend_Feed_Reader::registerExtension('media');) returns a null when running $item->getThumbnail().

Does anyone have any ideas?


Solution

  • I also did follow the guide at Zend.com and found out that there is a problem with the first code block, the arguments for Zend_Feed_Reader::addPrefixPath are in incorrect order, and has to be like this:

    if(!Zend_Feed_Reader::isRegistered('JungleBooks')) {
        Zend_Feed_Reader::addPrefixPath(
            'My_FeedReader_Extension', '/path/to/My/FeedReader/Extension'
        );
        Zend_Feed_Reader::registerExtension('JungleBooks');
    }
    

    I assume you registered your extension this way?

    That done, and with a custom extension I continued. Using the complete example from Zend.com just gave me an empty string. After trying some different notations for getting to the namespace like double colons ::, brackets [] and even @ symbols I almost gave up.

    And then something popped into mind; what if I try to fetch my XPath without a string() wrap, and so I did (I used your code to make it even clearer):

    class Zend_Feed_Reader_Extension_Media_Entry 
        extends Zend_Feed_Reader_Extension_EntryAbstract
    {
        public function getThumbnails()
        {
            if(isset($this->_data['thumbnails'])){
                return $this->_data['thumbnails'];
            }
    
            $thumbnail_list = $this->_xpath->evaluate(
                $this->getXpathPrefix() . '/media:thumbnail'
            );
            $thumbnails = array();
    
            // According to your XML sample there are multiple thumbnails per item, so we're looping through them and adding them to a simple array
            foreach($thumbnail_list as $_thumbnail_element){
                array_push($thumbnails, array(
                    'url'    => $_thumbnail_element->getAttribute('url'),
                    'width'  => $_thumbnail_element->getAttribute('width'),
                    'height' => $_thumbnail_element->getAttribute('height'),
                ));
            }
    
            if(!count($thumbnails)){
                $thumbnails = null;
            }
    
            $this->_data['thumbnails'] = $thumbnails;
    
            return $this->_data['thumbnails'];
        }
    
        protected function _registerNamespaces()
        {
            $this->_xpath->registerNamespace('media', 'http://search.yahoo.com/mrss');
        }
    }
    

    And voila, there are your thumbnails.