Reputation: 125
Another little thing has been driving me crazy... I want to pull in an RSS feed and display it using PHP. It asks for the mrss decription (because it doesn't have all the extra junk attached to it). The only problem is that the feed has advertisements. So when the script calls for the media description of an advertisement (for which there is none), the whole page fails.
I've tried using continue and an if...else based on length, but it's still not working..
$xml=("http://feeds.abcnews.com/abcnews/gmavideos");
$xmlDoc = new DOMDocument();
$xmlDoc->load($xml);
$x=$xmlDoc->getElementsByTagName('item');
for ($i=0; $i<=10; $i++)
{
$item_title=$x->item($i)->getElementsByTagName('title')
->item(0)->childNodes->item(0)->nodeValue;
$item_link=$x->item($i)->getElementsByTagNameNS('http://www.pheedo.com/namespace/pheedo', 'origLink')
->item(0)->childNodes->item(0)->nodeValue;
$item_desc=$x->item($i)->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'description')
->item(0)->childNodes->item(0)->nodeValue;
if ($x->length == 0) {
exit('etc.');
}
else {
echo ("<p><a href='" . $item_link
. "' target='_blank'>" . $item_title . "</a>");
echo ("<br />");
echo ($item_desc . "</p>");
}
}
Any guidance appreciated!
Upvotes: 2
Views: 517
Reputation: 243479
The only problem is that the feed has advertisements. So when the script calls for the media description of an advertisement (for which there is none), the whole page fails.
Use:
/*/channel/item[media:description]
Or, alternatively:
/*/channel/item[not(title='Advertisement:')]
I personally would use and recommend the first expression above.
Upvotes: 0
Reputation: 31631
Without seeing the error message I can't know for sure, but most likely the script is failing because of this line:
$item_desc=$x->item($i)->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'description')->item(0)->childNodes->item(0)->nodeValue;
If there is no description element, then getElementsByTagNameNS()
will return an empty DOMNodeList
, so the ->item(0)->childNodes
will fail.
You need to separate these out.
$item_desc_nodes = $x->item($i)->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'description');
if ($item_desc_nodes->length) {
$item_desc = $item_desc_nodes->item(0)->childNodes->item(0)->nodeValue;
} else {
continue;
}
Honestly, though, you should really be using XPath instead of getElementsByTagNameNS
.
You should also use ->textContent
instead of ->childNodes->item(0)->nodeValue
.
UPDATE: This is how I would accomplish the same task using XPath
$xml = 'http://feeds.abcnews.com/abcnews/gmavideos';
$xmlDoc = new DOMDocument();
$xmlDoc->load($xml);
$xpath = new DOMXPath($xmlDoc);
$xpath->registerNamespace('media', 'http://search.yahoo.com/mrss/');
$xpath->registerNamespace('pheedo', 'http://www.pheedo.com/namespace/pheedo');
// filter out the ads in the xpath expression itself by saying there must be
// a pheedo:origLink element in the item
$items = $xpath->query('/rss/channel/item[pheedo:origLink][position() < 11]');
$linktmpl = '<p><a href="%s" target="_blank">%s</a><br />%s</p>'."\n";
foreach($items as $item) {
$item_title = $xpath->evaluate('string(title)', $item);
$item_link = $xpath->evaluate('string(pheedo:origLink)', $item);
$item_desc = $xpath->evaluate('string(media:description)', $item);
$escaped = array_map('htmlspecialchars', array($item_link, $item_title, $item_desc));
vprintf($linktmpl, $escaped);
}
Upvotes: 3