PHP SoapServer(WSDL)如何将xml命名空间设置为项目而不是标题?

时间:2015-07-08 14:53:25

标签: php soap binding namespaces wsdl

我有一个基于wsdl的小型php soap服务器,它提供DLNA请求。服务器代码看起来像成千上万:

$srv = new SoapServer( "wsdl/upnp_av.wsdl" );
$srv->setClass( "ContentDirectory" );
$srv->handle();

它有效。对于程序,它成功返回SOAP响应:

<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:schemas-upnp-org:service:ContentDirectory:1">
<SOAP-ENV:Body>
<ns1:GetSearchCapabilitiesResponse>
<SearchCaps>*</SearchCaps>
</ns1:GetSearchCapabilitiesResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>

这是绝对正确的xml语法。但是我的大部分DLNA设备都不会接受这个答案(但东芝电视的效果非常好)。所以我从其他DLNA服务器上获取了Wireshark并跟踪了xml,并且发现,所有这些服务器都返回了另一个xml,命名空间在ns1主体定义,而不是在信封中。这是样本正确的行,所有设备都接受良好:

<?xml version="1.0" encoding="UTF-8"?>
<s:Envelope s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" xmlns:s="http://schemas.xmlsoap.org/soap/envelope/">
<s:Body>
<u:GetSearchCapabilitiesResponse xmlns:u="urn:schemas-upnp-org:service:ContentDirectory:1">
<SearchCaps>*</SearchCaps>
</u:GetSearchCapabilitiesResponse>
</s:Body>
</s:Envelope>

所以“ContentDirectory”xmlns刚刚从标题移入一个块。两个xmls在语法上都是正确的。

有些人也面临同样的问题:

  

Problem with WSDL

     

change soap prefixes in php

     

Soap Response Namespace issue

     

SoapServer maps functions incorectly when the wsdl messages have the same part name

     

PHP Soap Server response formatting

经过2天的研究,我想出了这个解决方法,将文档中的绑定更改为rpc方法:

<soap:binding style="document"   -->   <soap:binding style="rpc"

但是当我这样做时,php脚本只是崩溃了[在zend引擎里面的某个地方?],所以我在access.log中有一行提到500错误发生了,但是它没有显示在error.log中 - 该文件保持不变空(当然,所有其他500个错误都很好地转到了error.log)。

由于它太大,我上传了WSDL文件:http://pastebin.com/ZNG4DqAn

还有其他什么,我可以尝试解决这个问题吗?

请记住,电视处理这个xml语法是完全正确的,一切都运行得很好,但是android手机可能还需要其他需要命名空间的xml解析器吗?就在现在我已经准备好做preg_replaces()把那个该死的xmlns移到正确的地方:),但我认为这不是Jedies的路径:)

我的环境:PHP 5.4.20,Apache 2.2,Windows 2012

1 个答案:

答案 0 :(得分:0)

最后我不会成为绝地,我做了手动更换并且有效。

function replace_xmlns( $soapXml )
{
$marker1 = "xmlns:ns1=";
$marker2 = "<ns1:";

$startpos = strpos( $soapXml, $marker1 );
$endpos   = strpos( $soapXml, "\"", $startpos + 14 );

$namespace = substr( $soapXml, $startpos, $endpos - $startpos + 1 );
$soapXml   = str_replace( $namespace, "", $soapXml );

$m2start = mb_strpos( $soapXml, $marker2 );
$m2end   = mb_strpos( $soapXml, '>', $m2start );

$soapXml = substr_replace( $soapXml, " " . $namespace, $m2end, 0 );

return $soapXml;
}