2013-03-28 126 views
0

我試圖進入位於下面的SOAP中的<err:Errors>SimpleXML訪問元素 - PHP

<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soapenv:Header/> 
    <soapenv:Body> 
     <soapenv:Fault> 
      <faultcode>Client</faultcode> 
      <faultstring>An exception has been raised as a result of client data.</faultstring> 
      <detail> 
       <err:Errors xmlns:err="http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1"> 
        <err:ErrorDetail> 
         <err:Severity>Hard</err:Severity> 
         <err:PrimaryErrorCode> 
          <err:Code>120802</err:Code> 
          <err:Description>Address Validation Error on ShipTo address</err:Description> 
         </err:PrimaryErrorCode> 
        </err:ErrorDetail> 
       </err:Errors> 
      </detail> 
     </soapenv:Fault> 
    </soapenv:Body> 
</soapenv:Envelope> 

下面是我如何去做,但$ fault_errors->錯誤沒有任何東西。

$nameSpaces = $xml->getNamespaces(true); 
$soap = $xml->children($nameSpaces['soapenv']); 
$fault_errors = $soap->Body->children($nameSpaces['err']); 

if (isset($fault_errors->Errors)) { 
    $faultCode = (string) $fault_errors->ErrorDetail->PrimaryErrorCode->Code;    
} 
+0

注意,現在您的代碼依賴於'soapenv'前綴,這是一個非常糟糕的做法! – Evert

+0

即使是soapenv? – Slinky

+1

是的。分析器基本上應該忽略使用的前綴。如果xml名稱空間的前綴在夜間發生變化,那麼xml文檔的語義含義保持不變,並且解析器不應該中斷。儘管如此,命名空間url仍然是穩定的,所以在硬編碼中,而不是前綴。 – Evert

回答

1

你可以使用XPath查詢:

$ns = $xml->getNamespaces(true); 
$xml->registerXPathNamespace('err', $ns['err']); 

$errors = $xml->xpath("//err:Errors"); 
echo $errors[0]->saveXML(); // prints the tree 
+0

那麼我可以訪問嗎?喜歡這個? $ severity =(string)$ errors [0] - > ErrorDetail-> Severity; – Slinky

+0

@Slinky不,更像這樣:'(string)current($ errors [0] - > xpath(「err:ErrorDetail/err:Severity」)' –

+0

啊,我明白了,謝謝。 – Slinky

0

你試圖在XML一下子跳了下來幾個步驟。 ->運營商和->children()方法只是返回直接的孩子,不是任意的後代。

正如另一個答案中所述,您可以使用XPath跳轉,但如果您想要遍歷,則需要注意傳遞的每個節點的名稱空間,並在其更改時再次調用->children()

下面的代碼將其分解循序漸進(live demo):

$sx = simplexml_load_string($xml); 
// These are all in the "soapenv" namespace 
$soap_fault = $sx->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->Fault; 
// These are in the (undeclared) default namespace (a mistake in the XML being sent) 
echo (string)$soap_fault->children(null)->faultstring, '<br />'; 
$fault_detail = $soap_fault->children(null)->detail; 
// These are in the "err" namespace 
$inner_fault_code = (string)$fault_detail->children('http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1')->Errors->ErrorDetail->PrimaryErrorCode->Code;    
echo $inner_fault_code, '<br />'; 

當然,你也可以做一些或全部,在一氣呵成:

$inner_fault_code = (string) 
    $sx 
    ->children('http://schemas.xmlsoap.org/soap/envelope/')->Body->Fault 
    ->children(null)->detail 
    ->children('http://www.ups.com/XMLSchema/XOLTWS/Error/v1.1')->Errors->ErrorDetail->PrimaryErrorCode->Code;    
echo $inner_fault_code, '<br />';