2013-03-28 86 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 />';