我有一个基于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在语法上都是正确的。
有些人也面临同样的问题:
SoapServer maps functions incorectly when the wsdl messages have the same part name
经过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
答案 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;
}