PHP - 如何检查每个循环的元素?

时间:2015-04-04 21:31:15

标签: php xml loops dom

我使用下面的循环来解析XML文件。

$link = $item->getElementsByTagName('link')->item(0)->firstChild->nodeValue;
$image = $item->getElementsByTagName('enclosure')->item(0)->getAttribute('url');

但是,有些时候XML项目没有'enclosure'元素而我的整个页面都失败并出现以下错误

PHP Fatal error:  Call to a member function getAttribute() on a non-object

如何检查每个循环的元素,并将$ image变量替换为静态字符串(如果不存在)?

1 个答案:

答案 0 :(得分:2)

我建议您使用xpath。使用 DOMDocument DOMXPath ,您可以从DOMXPath::evaluate method获得极大的好处,因为您可以直接获取字符串值。如果查询的元素不存在,您将获得一个空字符串(您还可以检查存在count(),如果找不到节点,则返回0

示例:

$item  = $doc->getElementsByTagName('itme')->item(0);
$xpath = new DOMXPath($doc);

echo "link.....: ", $xpath->evaluate('string(.//link)', $item), "\n";
echo "enclosure: ", $xpath->evaluate('string(.//enclosure[@url])', $item), "\n";

我创建了一些示例XML

<feed-me>
    <item>
        <link>http://nytimes.com/2004/12/07FEST.html</link>
        <actor class="foo" xml:space="preserve"> </actor>
    </item>
</feed-me>

,输出

link.....: http://nytimes.com/2004/12/07FEST.html
enclosure: 

如此示例所示,第一个xpath表达式计算为<link>元素的文本内容。第二个表达式对空字符串进行评估,因为该属性不存在。

在PHP代码中访问对象时,从非现有元素获取属性的问题

$item->getElementsByTagName('enclosure')->item(0)->getAttribute('url');
                                             ^               ^
                                             |               |
                                   there is no item at       |
                                  index 0, this is NULL      |
                                                             |
                                                         NULL has no
                                                     getAttribute method
                                                        = FATAL ERROR

另一方面使用xpath表达式

 string(.//enclosure[@url])

内部表达式.//enclosure[@url]返回空节点列表,string() function返回""(空字符串)。否则,它返回该节点列表中第一个节点的字符串值(按文档顺序)。

总而言之,这使得以稳定的方式从文档中获取信息变得非常容易。但是你必须学习一些小的xpath语言。但是我们在Stackoverlow上也得到了很好的支持。

完整示例(和online demo to play around):

<?php
/**
 * PHP - How to check for element each loop?
 * @link http://stackoverflow.com/a/29452042/367456
 */

$buffer = <<<XML
<feed-me>
    <item>
        <link>http://nytimes.com/2004/12/07FEST.html</link>
        <actor class="foo" xml:space="preserve"> </actor>
    </item>
</feed-me>
XML;

$doc = new DOMDocument();
$doc->loadXML($buffer);
$xpath = new DOMXPath($doc);

$item = $doc->getElementsByTagName('itme')->item(0);

$xpath = new DOMXPath($doc);

echo "link.....: ", $xpath->evaluate('string(.//link)', $item), "\n";
echo "enclosure: ", $xpath->evaluate('string(.//enclosure[@url])', $item), "\n";

$item->getElementsByTagName('enclosure')->item(0)->getAttribute('url');