用 PHP 循环 XML

Looping XML with PHP

我已经阅读了我所关注的各种内容,但我似乎无法正常工作。我从 eBay Trading API 返回 XML,它正在工作,但我无法让一些节点回显...(我是 php / xml)

这是 XML 的示例(由于包含订单数据而被删除):

<?xml version="1.0" encoding="UTF-8"?>
<GetOrdersResponse xmlns="urn:ebay:apis:eBLBaseComponents">
  <Timestamp>2016-01-28T10:48:19.262Z</Timestamp>
  <Ack>Success</Ack>
  <Version>949</Version>
  <Build>E949_INTL_APIXO_17770994_R1</Build>
  <PaginationResult>
    <TotalNumberOfEntries>3</TotalNumberOfEntries>
  </PaginationResult>
  <HasMoreOrders>false</HasMoreOrders>
  <OrderArray>
    <Order>
      <OrderID>400930822745-519268006027</OrderID>
      <OrderStatus>Completed</OrderStatus>
      <AmountPaid currencyID="GBP">213.0</AmountPaid>
    </Order>
    <Order>
      <OrderID>191593173254-1228482367009</OrderID>
      <OrderStatus>Completed</OrderStatus>
      <AmountPaid currencyID="GBP">289.0</AmountPaid>
    </Order>
    <Order>
      <OrderID>400930822765-514681551027</OrderID>
      <OrderStatus>Completed</OrderStatus>
      <AmountPaid currencyID="GBP">238.0</AmountPaid>
    </Order>
  </OrderArray>
</GetOrdersResponse>​

这是我正在使用的PHP:

$responseDoc = new DomDocument();
$responseDoc->loadXML($responseXml);


$ackNode = $responseDoc->getElementsByTagName('Ack');
$paginationCategoryNode = $responseDoc->getElementsByTagName('PaginationResult');
$totalNode = $paginationCategoryNode->item(0)->getElementsByTagName('TotalNumberOfEntries');

$orders = [];
foreach ($responseDoc->OrderArray->Order as $order) {
    $orders[] = $order->toArray();
}

echo 'Order Ack: ', $ackNode->item(0)->nodeValue;
echo '<br />Sales Quantity: ', $totalNode->item(0)->nodeValue;

print_r(array_values($orders));


/*  also tried this also but didn't work:

foreach ($responseDoc->Order as $Order) {
    echo '<br />' . $Order->OrderStatus;
}
*/

我知道 API 调用有效,因为我可以回显 Ack:Success 和 TotalNumberOfEntries:3 但不确定如何获取订单 -> 订单 ID 或订单 - > 支付金额。

我想循环每个订单以获得每个订单的值...

非常感谢!

这可能是错误的:

foreach ($responseDoc->OrderArray->Order as $order) {
                                  ^^^^^^

您想在 Order 组件上循环,但由于有多个 <order> 标签,您需要在其父容器上循环,例如<OrderArray>

foreach ($responseDoc->OrderArray as $order) {
                                 ^---note the difference

你可以用同样的方法,你正在访问 AckTotalNumberOfEntries

要获取 Order 个节点的列表,您可以这样做:

$orderList = $responseDoc
               ->getElementsByTagName('OrderArray')->item(0)
               ->getElementsByTagName('Order');

然后你可以迭代它,但是在你的循环中你仍然在处理 DOMElement 对象所以你不能像简单对象一样使用它。

所以为了获得例如 OrderStatus 值,而不是

$order->OrderStatus

你必须做的:

$order->getElementsByTagName('OrderStatus')->item(0)->textContent;

另外请记住,没有像 DOMElement::toArray() 这样的函数,因此您应该在循环中分别访问每个子节点,以创建 $orders 数组。

最终循环可能如下所示:

$orders = [];
foreach ($orderList as $order) {    
    $orders[] = array(
        'OrderID' => $order->getElementsByTagName('OrderID')->item(0)->textContent,
        'OrderStatus' => $order->getElementsByTagName('OrderStatus')->item(0)->textContent,
        'AmountPaid' => $order->getElementsByTagName('AmountPaid')->item(0)->textContent.
        'AmountPaidCurrency' => $order->getElementsByTagName('AmountPaid')->item(0)->getAttribute('currencyID'),
    );
}

另请注意,我必须单独获取 AmountPaidcurrencyID 属性。这就是为什么不能简单地将 HTML 转换为数组的原因之一。

您必须以这种方式更正您的代码:

foreach ($responseDoc->getElementsByTagName('Order') as $order) {
    echo 'Order ID: ' . $order->getElementsByTagName('OrderID')->item(0)->nodeValue;
    echo '<br />Order Status: ' . $order->getElementsByTagName('OrderStatus')->item(0)->nodeValue;
    echo '<br />Amount Paid: ' . $order->getElementsByTagName('AmountPaid')->item(0)->nodeValue . ' ' . $order->getElementsByTagName('AmountPaid')->item(0)->getAttribute('currencyID');
}

如果你想打印数据。

相反,如果您想在数组中捕获数据:

$orders = [];
foreach ($responseDoc->getElementsByTagName('Order') as $order) {
    $row = array();
    $row['id'] = $order->getElementsByTagName('OrderID')->item(0)->nodeValue;
    $row['status'] = $order->getElementsByTagName('OrderStatus')->item(0)->nodeValue;
    $row['amount'] = $order->getElementsByTagName('AmountPaid')->item(0)->nodeValue . ' ' . $order->getElementsByTagName('AmountPaid')->item(0)->getAttribute('currencyID');
    $orders[] = $row;
}
print_r( $orders );

eval.in demo

注释:

因为 <Order> 节点在此上下文中是单义词,所以我使用

$responseDoc->getElementsByTagName('Order')

但你也可以使用

$responseDoc->getElementsByTagName('OrderArray')->item(0)->getElementsByTagName('Order')

$responseDoc->getElementsByTagName('OrderArray')->item(0)->childNodes