如何使用nuSOAP处理具有多个命名空间的消息

7

我正在尝试使用nuSOAP访问一个使用多个命名空间的WebService(因为我只能使用PHP4)。这可能吗?

一个示例请求消息如下所示:

<soapenv:Envelope ...
  xmlns:ns1="http://domain.tld/namespace1"
  xmlns:ns2="http://domain.tld/namespace2">
  <soapenv:Header/>
  <soapenv:Body>
    <ns1:myOperation>
      <ns2:Person>
        <ns2:Firstname>..</ns2:Firstname>
        ..
      </ns2:Person>
      <ns1:Attribute>..</ns1:Attribute>
    </ns1:myOperation>
  </soapenv:Body>
</soapenv:Envelope>

我尝试了以下操作:
$client = new nusoap_client("my.wsdl", true);
$params = array(
  'Person' => array(
    'FirstName'  => 'Thomas',
    ..
   ),
   'Attribute' => 'foo'
 );

 $result = $client->call('myOperation', $params, '', 'soapAction');

希望nuSOAP会尝试将这些名称匹配到正确的命名空间和节点。然后我尝试使用soapval()生成元素及其命名空间 - 但是如果我调用一个操作,nuSOAP将创建以下请求:

<SOAP-ENV:Envelope ...>
  <SOAP-ENV:Body>
    <queryCCApplicationDataRequest xmlns="http://domain.tld/namespace1"/>
  </SOAP-ENV:Body>
</SOAP-ENV:Envelope>

所以在"匹配"阶段出现了一些问题。

4个回答

5

在进行匹配尝试后,我找到了两种可能的解决方案:

1)不使用WSDL创建nusoap_client和soapval()来创建消息。这种方法的缺点是消息包含大量的开销(每个元素中都定义了命名空间),并不是很好。

2)不要依赖参数匹配,而是构建xml回复并将所有前缀定义放在第一个元素中-例如:

$params = "<ns1:myOperation xmlns:ns1="..." xmlns:ns2="...">
      <ns2:Person>
        <ns2:Firstname>..</ns2:Firstname>
        ..
      </ns2:Person>
      <ns1:Attribute>..</ns1:Attribute>
    </ns1:myOperation>";

这仍然不是一个非常好的解决方案,但它可以工作 :-)


4

在Irwin的帖子基础上,我手动创建了XML,并让nusoap完成其余工作。我的Web主机没有php soap扩展程序,所以我必须使用nusoap,并且我尝试使用的Web服务要求每个标记都有命名空间(例如,在此示例中的用户名和密码上)。

require_once('lib/nusoap.php');

$client = new nusoap_client('https://service.somesite.com/ClientService.asmx');
$client->soap_defencoding = 'utf-8';
$client->useHTTPPersistentConnection(); // Uses http 1.1 instead of 1.0
$soapaction = "https://service.somesite.com/GetFoods";

$request_xml = '<?xml version="1.0" encoding="utf-8" ?>
<env:Envelope xmlns:xsd="http://www.w3.org/2001/XMLSchema"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:env="http://schemas.xmlsoap.org/soap/envelope/">
  <env:Body>
    <n1:GetFoods xmlns:n1="https://service.somesite.com">
      <n1:username>banjer</n1:username>
      <n1:password>theleftorium</n1:password>
    </n1:GetFoods>
  </env:Body>
</env:Envelope>
';

$response = $client->send($request_xml, $soapaction, ''); 

echo '<h2>Request</h2><pre>' . htmlspecialchars($client->request, ENT_QUOTES) . '</pre>';
echo '<h2>Response</h2><pre>' . htmlspecialchars($client->response, ENT_QUOTES) . '</pre>';
echo '<h2>Debug</h2><pre>' . htmlspecialchars($client->getDebug(), ENT_QUOTES) . '</pre>';

然后我遇到了一个错误,错误信息如下:
Notice: Undefined property: nusoap_client::$operation in ./lib/nusoap.php  on line 7674

所以我采取了懒惰的方式,进入nusoap.php并在第7674行之前添加了以下代码,使其正常运行:

    if(empty($this->operation)) {
        $this->operation = "";
    }

在搜索了几天互联网后,这是唯一帮助我解决问题的东西。谢谢!虽然我没有遇到那个错误,但我不得不设置 $client->endpoint = '<endpoint url>'; - Cypher909

2
另一种解决此问题的方法是修改nusoap_client :: call()函数。 在nusoap.php中,该行代码(版本1.123中的第7359行)旁边添加以下代码: $nsPrefix = $this->wsdl->getPrefixFromNamespace($namespace); 我添加了这一行代码。
$nsPrefix = $this->wsdl->getPrefixFromNamespace("other_ns_name");

它确实起作用了!由于我只需要这个库来完成一个项目,所以硬编码这个技巧对我来说是可以的。否则,我会更深入地挖掘并修改该函数,使其接受数组而不是字符串作为命名空间参数。


0

嗯,看起来链接目前无法使用。从你的说法来看,他们采用了类似的方法(手动创建XML),对吗? - wilth

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接