2013-03-25 181 views
0

我在解析名爲「q0:」的嵌套名稱空間中的標記時存在一個小問題,位於下方。SimpleXML解析嵌套名稱空間 - PHP

//Tag that I am trying to parse 
    <q0:CustomerTransactionId> 

由於某些原因,我能夠找到所有的「v12:」名稱空間標籤,但不是「q0:」。

謝謝!

這裏是XML

<?xml version="1.0" encoding="UTF-8"?> 
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
<env:Header 
     xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
     xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"/> 
<soapenv:Body> 
<v12:ProcessShipmentReply 
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/" 
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
    xmlns:v12="http://fedex.com/ws/ship/v12"> 
    <v12:HighestSeverity>ERROR</v12:HighestSeverity> 
    <v12:Notifications> 
     <v12:Severity>ERROR</v12:Severity> 
     <v12:Source>ship</v12:Source> 
     <v12:Code>3058</v12:Code> 
     <v12:Message>Recipient Postal code or routing code is required</v12:Message> 
     <v12:LocalizedMessage>Recipient Postal code or routing code is required</v12:LocalizedMessage> 
    </v12:Notifications> 
    <q0:TransactionDetail xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:q0="http://fedex.com/ws/ship/v12"> 
     <q0:CustomerTransactionId>21445634</q0:CustomerTransactionId> 
    </q0:TransactionDetail><q0:Version xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:q0="http://fedex.com/ws/ship/v12"> 
    <q0:ServiceId>ship</q0:ServiceId> 
    <q0:Major>12</q0:Major> 
    <q0:Intermediate>0</q0:Intermediate> 
    <q0:Minor>0</q0:Minor> 
    </q0:Version> 
    </v12:ProcessShipmentReply> 
    </soapenv:Body> 
    </soapenv:Envelope> 

這裏是我的解析

$xml = simplexml_load_string($result, NULL, NULL, 'http://schemas.xmlsoap.org/soap/envelope/'); 
    $xml->registerXPathNamespace('env', 'http://schemas.xmlsoap.org/soap/envelope/'); 
    $xml->registerXPathNamespace('v12', 'http://fedex.com/ws/ship/v12'); 
    $xml->registerXPathNamespace('q0', 'http://fedex.com/ws/ship/v12'); 

    $bodies = $xml->xpath('env:Body'); 

    foreach($bodies as $body){ 

     $reply = $body->children('v12', TRUE)->ProcessShipmentReply; 
     $reply2 = $body->children('q0', TRUE)->TransactionDetail; 

     $custInfoArr['status'] = (string) $reply->HighestSeverity; 

     if(strtolower($custInfoArr['status'])=="error"){ 


      $custInfoArr['invoiceNum'] = (string)$reply2->CustomerTransactionId; 
      $custInfoArr['notificationSeverity']= (string) $reply->Notifications->Severity; 
      $custInfoArr['notificationSource']= (string) $reply->Notifications->Source; 
      $custInfoArr['notificationCode']= (string) $reply->Notifications->Code; 
      $custInfoArr['notificationMessage']= (string) $reply->Notifications->Message; 
      $custInfoArr['notificationLocalizedMessage']= (string) $reply->Notifications->LocalizedMessage; 

     } 

     $custInfoArr['trackingCode'] = (string) $reply->CompletedShipmentDetail->CompletedPackageDetails->TrackingIds->TrackingNumber; 
     $custInfoArr['labelCode'] = (string) $reply->CompletedShipmentDetail->CompletedPackageDetails->Label->Parts->Image; 
     $custInfoArr['labelCode'] = base64_decode($custInfoArr['labelCode']); 

    } 

回答

1

<q0:TransactionDetail>不是<env:Body>一個孩子,這是<v12:ProcessShipmentReply>一個孩子,所以你需要在$reply內部尋找它,而不是$body$reply2 = $reply->children('q0', TRUE)->TransactionDetail;

要記住的重要一點是,->TagName運營商和->children()方法只查看特定節點的直接子女,他們沒有像XPath那樣進行「深度搜索」。

事實上,前瞻性,既​​和q0:是同一個命名空間(「http://fedex.com/ws/ship/v12」)的別名,所以下一行可以只是$reply2 = $reply->TransactionDetail。如果你只是說$reply = $body->children('http://fedex.com/ws/ship/v12')->ProcessShipmentReply而不是依賴別名,這變得更清晰(並且更安全,因爲這些別名可能會改變)。順便說一下,除非你用它來做其他事情,你也可以擺脫所有的XPath代碼(包括所有的registerXPathNamespace調用),並且只寫$body = $xml->children('http://schemas.xmlsoap.org/soap/envelope/')->Body(我敢肯定,SOAP只允許一個Body信息)。

+0

謝謝。我非常感謝你的解釋 – Slinky 2013-03-27 16:00:18