2010-11-16 122 views
37

SOAP XML:如何解析SOAP XML?

<?xml version="1.0" encoding="utf-8"?> 
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
    <soap:Body> 
    <PaymentNotification xmlns="http://apilistener.envoyservices.com"> 
     <payment> 
     <uniqueReference>ESDEUR11039872</uniqueReference>  
     <epacsReference>74348dc0-cbf0-df11-b725-001ec9e61285</epacsReference> 
     <postingDate>2010-11-15T15:19:45</postingDate> 
     <bankCurrency>EUR</bankCurrency> 
     <bankAmount>1.00</bankAmount> 
     <appliedCurrency>EUR</appliedCurrency> 
     <appliedAmount>1.00</appliedAmount> 
     <countryCode>ES</countryCode> 
     <bankInformation>Sean Wood</bankInformation> 
    <merchantReference>ESDEUR11039872</merchantReference> 
    </payment> 
    </PaymentNotification> 
    </soap:Body> 
</soap:Envelope> 

如何获得 '金' 元素?

我尝试解析(PHP)

$xml = simplexml_load_string($soap_response); 
$xml->registerXPathNamespace('soap', 'http://schemas.xmlsoap.org/soap/envelope/'); 
foreach ($xml->xpath('//payment') as $item) 
{ 
    print_r($item); 
} 

结果为空:( 任何想法如何分析它是否正确?

+0

欢迎来到SO。下次单击textarea顶部的格式按钮,以便代码更易于阅读。 – stillstanding 2010-11-16 13:19:24

+0

@stillstanding:噢,显然我改写就像你提交它:) – BoltClock 2010-11-16 13:21:49

+0

等待帮助..... – Anton 2010-11-16 13:27:53

回答

-2

为什么不ü尝试使用绝对路径的XPath

//soap:Envelope[1]/soap:Body[1]/PaymentNotification[1]/payment 

或者因为你知道,这是一个和支付没有任何属性,只需直接从支付选择

//soap:Envelope[1]/soap:Body[1]/PaymentNotification[1]/payment/* 
+1

foreach($ xml-> xpath('// soap:Envelope [1]/soap:Body [1]/PaymentNotification [1]/payment/*')as $ item) { print_r($ item); } 也是空的( – Anton 2010-11-16 13:39:26

+0

试着给你的第二个命名空间中的实际值和定义,然后 – almightyBob 2010-11-16 13:51:35

+0

你能给例如请 – Anton 2010-11-16 13:58:25

21

在您的代码中,您正在查询默认名称空间中的payment元素,但在XML响应中,它声明为http://apilistener.envoyservices.com名称空间。

所以,你缺少一个命名空间声明

$xml->registerXPathNamespace('envoy', 'http://apilistener.envoyservices.com'); 

现在你可以使用envoy命名空间前缀在你的XPath查询:

xpath('//envoy:payment') 

完整的代码是:

$xml = simplexml_load_string($soap_response); 
$xml->registerXPathNamespace('envoy', 'http://apilistener.envoyservices.com'); 
foreach ($xml->xpath('//envoy:payment') as $item) 
{ 
    print_r($item); 
} 

:我删除了soap命名空间声明,你似乎没有使用它(这是唯一有用的,如果你XPath查询您将使用命名空间前缀)。

41

PHP版本> 5.0有一个很好的SoapClient的集成。哪些不需要解析响应xml。这里有一个简单的例子

$client = new SoapClient("http://path.to/wsdl?WSDL"); 
$res = $client->SoapFunction(array('param1'=>'value','param2'=>'value')); 
echo $res->PaymentNotification->payment; 
+0

救了我很多努力的人! – 2012-05-29 06:01:05

+2

这是什么SoapFunction? – Edward 2013-06-11 12:08:43

+0

@Edward它是您想要访问的SOAP服务的WSDL中定义的任何函数(操作) – Ivan 2013-06-11 15:42:37

6
$xml = '<?xml version="1.0" encoding="utf-8"?> 
       <soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"> 
        <soap:Body> 
        <PaymentNotification xmlns="http://apilistener.envoyservices.com"> 
         <payment> 
         <uniqueReference>ESDEUR11039872</uniqueReference> 
         <epacsReference>74348dc0-cbf0-df11-b725-001ec9e61285</epacsReference> 
         <postingDate>2010-11-15T15:19:45</postingDate> 
         <bankCurrency>EUR</bankCurrency> 
         <bankAmount>1.00</bankAmount> 
         <appliedCurrency>EUR</appliedCurrency> 
         <appliedAmount>1.00</appliedAmount> 
         <countryCode>ES</countryCode> 
         <bankInformation>Sean Wood</bankInformation> 
        <merchantReference>ESDEUR11039872</merchantReference> 
        </payment> 
        </PaymentNotification> 
        </soap:Body> 
       </soap:Envelope>'; 
     $doc = new DOMDocument(); 
     $doc->loadXML($xml); 
     echo $doc->getElementsByTagName('postingDate')->item(0)->nodeValue; 
     die; 

结果是:

2010-11-15T15:19:45 
+0

这会工作,但它在技术上不正确。您正在考虑将SOAP XML响应作为DOM文档,但事实并非如此。 – 2014-10-26 05:34:01

56

一个来处理命名空间前缀最简单的方法是简单地通过它通过对SimpleXML的,如之前从XML响应带他们如下:

$your_xml_response = '<Your XML here>'; 
$clean_xml = str_ireplace(['SOAP-ENV:', 'SOAP:'], '', $your_xml_response); 
$xml = simplexml_load_string($clean_xml); 

这将返回如下:

SimpleXMLElement Object 
(
    [Body] => SimpleXMLElement Object 
     (
      [PaymentNotification] => SimpleXMLElement Object 
       (
        [payment] => SimpleXMLElement Object 
         (
          [uniqueReference] => ESDEUR11039872 
          [epacsReference] => 74348dc0-cbf0-df11-b725-001ec9e61285 
          [postingDate] => 2010-11-15T15:19:45 
          [bankCurrency] => EUR 
          [bankAmount] => 1.00 
          [appliedCurrency] => EUR 
          [appliedAmount] => 1.00 
          [countryCode] => ES 
          [bankInformation] => Sean Wood 
          [merchantReference] => ESDEUR11039872 
         ) 

       ) 

     ) 

) 
+2

命名空间通常会产生误导,并且删除它似乎是恢复正确的xml对象的最快(黑客)方式。 thx – 2014-12-17 13:09:52

+14

真棒解决方案。肥皂很烂。 – 2015-06-18 05:18:48

+3

在我的情况下,我不得不向str_ireplace添加更多的数组值,但最终这是我发现的唯一工作解决方案。 Upvoted。还赞同@JohnBallinger肥皂太烂了。 – GTCrais 2015-11-19 17:11:11

0

如果随后需要将任何对象解析为数组,则这也相当不错: $ array = json_decode(json_encode($ responseXmlObject),true);