如何解析SOAP XML?

Ant*_*ton 49 php xml soap

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>
Run Code Online (Sandbox Code Playgroud)

如何获得"付款"元素?

我试着解析(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);
}
Run Code Online (Sandbox Code Playgroud)

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

Ara*_*ran 86

处理名称空间前缀的最简单方法之一就是将它们从XML响应中删除,然后再将其传递给simplexml,如下所示:

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

这将返回以下内容:

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
                        )

                )

        )

)
Run Code Online (Sandbox Code Playgroud)

  • 很棒的解决方案.肥皂糟透了. (31认同)
  • 命名空间通常会产生误导,删除它似乎是恢复正常xml对象的最快(黑客)方式.谢谢 (4认同)
  • 在我的情况下,我不得不向str_ireplace添加几个数组值,但最后这是我找到的唯一可行解决方案.Upvoted.也同意@JohnBallinger肥皂糟透了. (3认同)

Iva*_*van 46

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;
Run Code Online (Sandbox Code Playgroud)

  • 什么是SoapFunction? (2认同)

Nee*_*aks 23

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

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

$xml->registerXPathNamespace('envoy', 'http://apilistener.envoyservices.com');
Run Code Online (Sandbox Code Playgroud)

现在,您可以envoy在xpath查询中使用名称空间前缀:

xpath('//envoy:payment')
Run Code Online (Sandbox Code Playgroud)

完整的代码是:

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

注意:我删除了soap名称空间声明,因为您似乎没有使用它(只有在xpath查询中使用名称空间前缀时才有用).


Bảo*_*Nam 13

$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;
Run Code Online (Sandbox Code Playgroud)

结果是:

2010-11-15T15:19:45
Run Code Online (Sandbox Code Playgroud)

  • 这会奏效,但在技术上并不正确。您正在考虑将 SOAP XML 响应视为 DOM 文档,但事实并非如此。 (2认同)

小智 -2

你为什么不尝试使用绝对 xPath

//soap:Envelope[1]/soap:Body[1]/PaymentNotification[1]/payment
Run Code Online (Sandbox Code Playgroud)

或者因为您知道这是一次付款并且付款没有任何属性,只需直接从付款中选择

//soap:Envelope[1]/soap:Body[1]/PaymentNotification[1]/payment/*
Run Code Online (Sandbox Code Playgroud)