0

注文を含む 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>1 つのファイルに多数のノード。すべてが正しいのですが、突然、このような支払い情報なしで注文を受け取ります

<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 の例ではすべて問題ありませんが、2 番目の XML の例の注文に出くわすと、私のスクリプトは例外Trying to get property of non-objectをスローし、明らかにファイルの残りの解析を停止します。スクリプトを停止せずに、残りのファイルの解析を続行し
たいと考えています。私はあなたに「黙って」オペレーターを望んでいませんが、他に方法はありません.@

4

2 に答える 2

1

<payments>支払いデータ (paymentノードなど)があることを確認するロジックを追加する必要があります。

foreach ($orders as $order) {
    if ($order->payments->count()) {
        // has payment data... run your payment code
    }
}

アップデート

ドキュメントは上記がPHP> 5.3で動作するはずだと主張していますが、OPの場合に返され1ました(理由はわかりません)。

最終的に必要なものは次のとおりです。

count($order->payments->children())
于 2013-02-06T15:17:46.027 に答える
0

SimpleXML にはいくつかの魔法が備わっています。(既存または非存在の)<payment>要素にアクセスする方法を見てみましょう。

$order->payments->payment

これは (常に!)要素内の要素の数がゼロ以上であるSimpleXMLElementかどうかに関係なく、結果になります。<payment><payments>

ただし、カウントが実際にゼロの場合、最初の<payment>要素にアクセスすると次が返されNULLます。

$order->payments->payment[0]

これは、最初の (SimpleXML ではゼロベースのインデックス) 支払い要素にアクセスしています。存在しないため、結果は になりNULLます。したがって、これを if-check できます。

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'};
}

ただし、このエクスカーションは、おそらく で最も意図されている方法を実際に示すには完全ではありませんSimpleXMLElementSimpleXMLElementこれは、空が偽に等しいという事実に基づいています。

foreach ($orders as $order) 
{
    if (!$order->payments->payment) 
        continue;

    $var = $order->payments->payment->{'custom-method'}->{'method-name'};
}

これらすべての例が示すように、SimpleXML を少し調べて、それが魔法であることを理解して、その恩恵を受けることができるようにする必要があります。

魔法の少ないインターフェイスを好む場合は、姉妹をチェックしてDOMDocumentください。

とは独立してSimpleXMLElementTraversable(それも同様です) があるときはいつでもiterator_count、反復回数を返すために呼び出される関数を利用できます。a の場合、SimpleXMLElementそれは子供の数を意味します。

于 2013-02-07T15:41:48.613 に答える