我有一个包含订单的XML文件。
<?xml version="1.0" encoding="UTF-8"?>
<orders>
<order order-no="1234567">
<order-date>2012-09-15T12:28:45.000Z</order-date>
<invoice-no>123</invoice-no>
<customer>
<customer-no>1234</customer-no>
<customer-name>test</customer-name>
</customer>
<payments>
<payment>
<custom-method>
<method-name>example</method-name>
</custom-method>
<amount>12334</amount>
</payment>
</payments>
</order>
<order>
.......
</order>
</orders>
一个文件中有许多<order>
个节点。一切都是正确的但是我突然得到一个没有任何支付信息的订单
<orders>
<order order-no="1234567">
<order-date>2012-09-15T12:28:45.000Z</order-date>
<invoice-no>123</invoice-no>
<customer>
<customer-no>1234</customer-no>
<customer-name>test</customer-name>
<billing-address/>
</customer>
<payments/>
</order>
注意空<payments/>
节点。
我的PHP脚本如下所示:
$file = file_get_contents('orders.xml');
$orders = new SimpleXMLElement($file);
foreach ($orders as $order) {
$var = $order->payments->payment->{'custom-method'}->{'method-name'};
}
使用第一个XML示例一切都很好但是当我偶然发现第二个XML示例中的订单时,我的脚本会抛出异常Trying to get property of non-object
并显然停止解析文件的其余部分。
我喜欢我的脚本不停止并继续解析文件的其余部分。我不想要你关闭&#34;闭嘴&#34; @
运营商,但我没有看到任何其他方式。
答案 0 :(得分:1)
您需要添加逻辑以确保<payments>
具有付款数据(即payment
个节点)。
foreach ($orders as $order) {
if ($order->payments->count()) {
// has payment data... run your payment code
}
}
即使上面的docs claim适用于PHP&gt; 5.3,它在OP的情况下返回1
(不确定原因)。
最终需要以下内容:
count($order->payments->children())
答案 1 :(得分:0)
SimpleXML带有一些 magic 。让我们看看您如何访问(现有的或不存在的)<payment>
元素:
$order->payments->payment
无论SimpleXMLElement
元素中<payment>
个元素的数量是零还是更大,这将(始终!)产生<payments>
。
但是,如果计数实际为零,则访问第一个<payment>
元素将返回NULL
:
$order->payments->payment[0]
这是访问第一个(SimpleXML中从零开始的索引)付款元素。因为它不存在,导致NULL
。所以你可以检查一下:
foreach ($orders as $order)
{
if (!$order->payments->payment[0])
continue;
$var = $order->payments->payment->{'custom-method'}->{'method-name'};
}
另一个答案建议使用SimpleXMLElement::count()
方法。它计算一个元素的子元素并且它也可以工作,但另一个答案表明使用它的位置错误,正确的位置是<payment>
元素,而不是<payments>
元素:
$order->payments->payment->count()
这将返回您要检查的0
(零)个元素。所以这同样有效:
foreach ($orders as $order)
{
if (!$order->payments->payment->count())
continue;
$var = $order->payments->payment->{'custom-method'}->{'method-name'};
}
然而,这次游览并不能完全显示出一种可能最适合SimpleXMLElement
的方式。它基于以下事实:空SimpleXMLElement
等于false:
foreach ($orders as $order)
{
if (!$order->payments->payment)
continue;
$var = $order->payments->payment->{'custom-method'}->{'method-name'};
}
正如所有这些示例所示,您需要稍微探索SimpleXML以了解它的魔力,以便您可以从中受益。
如果你喜欢魔法较少的界面,请结识姐妹DOMDocument
。
独立于SimpleXMLElement
,只要你有Traversable
(它也是如此),你可以使用一个名为iterator_count
的函数来回馈迭代。对于SimpleXMLElement
,它表示孩子的数量。