4

首先让我说我不精通解析 XML 和/或编写 PHP。我一直在研究和拼凑我正在做的事情,但我被困住了。

我正在尝试创建一个基本的 if/else 语句:如果节点不为空,则写入节点的内容。

这是我正在调用的 XML 的片段:

<channel>
    <item>
      <title>This is a test</title>
      <link />
      <description>Test description</description>
      <category>Test category</category>
      <guid />
    </item>
  </channel>

这是我到目前为止的PHP:

<?php
    $alerts = simplexml_load_file('example.xml');
    $guid = $alerts->channel->item->guid;

    if ($guid->count() == 0) {
    print "// No alert";
}
    else {
        echo "<div class='emergency-alert'>".$guid."</div>";
}

?>

显然,“guid”是一个空节点,但它正在返回:

<div class="emergency-alert"> </div>

我究竟做错了什么?:(

PS,我试过 hasChildren() 也没有用。

4

3 回答 3

5

In PHP a SimpleXMLElement which represents an empty XML element (self-closing tag or empty open/close tag pair with no content) casts to boolean FALSE. This is perhaps a bit unexpected, as normally every object in PHP casts to boolean TRUE:

var_dump((bool) new SimpleXMLElement("<guid/>")); # bool(false)

var_dump((bool) new SimpleXMLElement("<guid></guid>")); # bool(false)

var_dump((bool) new SimpleXMLElement("<guid> </guid>")); # bool(true)

This special rule is documented in the PHP manual on Converting to boolean.

You can make use of that to check whether or not the <guid> element you have is empty. However it's important here, you ask for the element specifically. In your existing code:

$guid = $alerts->channel->item->guid;

you're not asking for a specific <guid> element, but for all which are children of the parent <item> element. These kind of SimpleXMLElement objects cast to boolean true unless they contain zero elements (compare with your use of SimpleXMLElement::count()).

Different to that, if you obtain the first <guid> element by index, you will get a SimpleXMLElement of that index or NULL in case the element does not exist (that means, there is no <guid> element).

Both - non-existing element as NULL or the existing, empty one - will cast to boolean false which can be easily used in your if/else statement:

$guid = $alerts->channel->item->guid[0];
                                    ### zero is the index of the first element
if ((bool) $guid) {
    # non-empty, existing <guid> element
} else {
    # empty or non-existing
}

This then answers your question.

于 2014-11-01T16:12:14.947 回答
5

@Wrikken 是对的。XPath 是查询 XML 文档的首选方式。但是回答您的问题,在您的简单情况下,您可以通过将 SimpleXMLElement 转换为字符串来检查节点值是否为空:

if ( !$guid->__toString() ) {
    print "No alert";
}
于 2014-10-30T18:23:40.233 回答
3
foreach($alerts->xpath("//item/guid[normalize-space(.)!='']") as $guid){
        echo "<div class='emergency-alert'>".$guid."</div>";
}

它有什么作用?

  1. xpath:一种查询xml文档的简单方法
  2. normalize-space:去掉前导、尾随和重复空格的参数字符串(即:<guid> </guid>不是空字符串,它是' ',但这个将其转换为''
  3. .是节点的文本内容
于 2014-10-30T17:52:11.273 回答