在PHP中的非对象上调用成员函数getAttribute()?

时间:2015-09-16 08:18:56

标签: php xml rss

我正在尝试从RSS源中获取图像。以下是Feed的结构:

<item>
<title>Title Here....</title>
<link>Link Here....</link>
<description>Description Here...</description>
<comments>Comments Here.</comments>
<pubDate>Tue, 15 Sep 2015 22:54:00 +0000</pubDate>
<guid isPermaLink="false">59551 at http://winsupersite.com</guid>
<media:thumbnail url="http://winsupersite.com/site-files/winsupersite.com/files/imagecache/thumb_img/uploads/2015/09/windowsrt81update3hero.png" />
<media:content url="http://winsupersite.com/site-files/winsupersite.com/files/uploads/2015/09/windowsrt81update3hero.png" medium="image">
</media:content>
</item>

这是我的PHP代码:

$rss = new DOMDocument();
$rss->load('http://winsupersite.com/rss.xml');
foreach ($rss->getElementsByTagName('item') as $node) {
   $title = $node->getElementsByTagName('title')->item(0)->nodeValue;
   $src   = $node->getElementsByTagName('thumbnail')->item(0)->getAttribute('url');
   $link  = $node->getElementsByTagName('link')->item(0)->nodeValue;
}

但我收到错误:

  

在非对象

上调用成员函数getAttribute()

为什么我收到此错误? thumbnail标记和url属性都存在。

以下是$ rss上var_dump的结果:

object(DOMDocument)#1 (34) { 
["doctype"]=> NULL ["implementation"]=> string(22) "(object value omitted)" 
["documentElement"]=> string(22) "(object value omitted)" ["actualEncoding"]=> string(5) "utf-8" 
["encoding"]=> string(5) "utf-8" ["xmlEncoding"]=> string(5) "utf-8" ["standalone"]=> bool(true) 
["xmlStandalone"]=> bool(true) ["version"]=> string(3) "1.0" ["xmlVersion"]=> string(3) "1.0" ["strictErrorChecking"]=> bool(true)        ["documentURI"]=> string(31) "http://winsupersite.com/rss.xml" 
["config"]=> NULL ["formatOutput"]=> bool(false) ["validateOnParse"]=> bool(false) 
["resolveExternals"]=> bool(false) ["preserveWhiteSpace"]=> bool(true) ["recover"]=> bool(false) ["substituteEntities"]=> bool(false) ["nodeName"]=> string(9) "#document" ["nodeValue"]=> NULL ["nodeType"]=> int(9) ["parentNode"]=> NULL 
["childNodes"]=> string(22) "(object value omitted)" ["firstChild"]=> string(22) "(object value omitted)" ["lastChild"]=> string(22) "(object value omitted)" ["previousSibling"]=> NULL ["attributes"]=> NULL 
["ownerDocument"]=> NULL ["namespaceURI"]=> NULL ["prefix"]=> string(0) "" ["localName"]=> NULL ["baseURI"]=> string(31) "http://winsupersite.com/rss.xml" ["textContent"]=> string(27278) " SuperSite for Win........ Just text after this

3 个答案:

答案 0 :(得分:1)

您只发布了没有命名空间定义的XML的一部分。您应该在祖先节点上具有类似xmlns:media="http://search.yahoo.com/mrss/"的命名空间定义。

DOM在解析XML时使用定义来解析前缀。具有前缀的元素和属性节点属于命名空间。您可以阅读{http://search.yahoo.com/mrss/}:thumbnail之类的名称。命名空间允许将不同的格式与相同的节点名称混合,而不会引起冲突。

大多数DOM方法都有两个版本,默认方法和带后缀的变体&#39; NS&#39;这是名称空间感知。

$src = $node
  ->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'thumbnail')
  ->item(0)
  ->getAttribute('url');

DOMNode::getElementsByTagName[NS]()始终返回节点列表,此列表可以为空。如果访问空列表的第一项,则结果为错误。为了使您的源稳定,您需要在访问之前验证列表是否有项目。

或者您可以使用Xpath表达式。它们更强大,允许您从DOM中获取节点列表或标量值。

$document = new DOMDocument();
$document->load($feedUrl);
$xpath = new DOMXpath($document);
$xpath->registerNamespace('m', 'http://search.yahoo.com/mrss/');

foreach ($xpath->evaluate('//item') as $item) {
  var_dump(
    [
      'title' => $xpath->evaluate('string(title)', $item),
      'src' => $xpath->evaluate('string(m:thumbnail/@url)', $item),
      'link' => $xpath->evaluate('string(link)', $item)
    ]
  );
}

m:thumbnail/@url将获取url命名空间中thumbnail子节点的http://search.yahoo.com/mrss/属性。 string()会将节点强制转换为字符串,如果没有找到节点,它将返回一个空字符串。

答案 1 :(得分:0)

thumbnail位于media命名空间内,因此您需要使用getElementsByTagNameNS来访问它。

您没有包含完整的RSS文档,但基本上您需要的命名空间应该在标题中,例如,如果它是&#34; http://search.yahoo.com/mrss/&#34;,您的代码将是:

$src = $node->getElementsByTagNameNS('http://search.yahoo.com/mrss/', 'thumbnail')->item(0)->getAttribute('url');

答案 2 :(得分:0)

检查一下,

$rss = new DOMDocument();
$rss->load('http://winsupersite.com/rss.xml');
foreach ($rss->getElementsByTagName('item') as $node) {
   $title = $node->getElementsByTagName('title')->item(0)->nodeValue;
   $src   = $node->getElementsByTagName('media:thumbnail')->item(0)->getAttribute('url');
   $link  = $node->getElementsByTagName('link')->item(0)->nodeValue;
}

它将解决您的问题。