简体   繁体   English

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

[英]PHP SoapServer (WSDL) How to set xml namespace to an item instead of header?

I have a tiny php soap server, that based on wsdl, and it serves DLNA requests. 我有一个基于wsdl的小型php soap服务器,它可以处理DLNA请求。 The server code looks like thousands of others: 服务器代码看起来像成千上万的其他代码:

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

and it works. 而且有效。 For the procedures it successfully returns SOAP responses: 对于该过程,它成功返回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>

And this is absolutely correct xml syntax. 这是绝对正确的xml语法。 But most of my DLNA devices won't accept this answer (but Toshiba TV works very well with it). 但是我的大多数DLNA设备都不会接受此答案(但是东芝电视公司的效果很好)。 So I took Wireshark and traced xml from other DLNA servers, and figured out, that all of them return slightly another xml, with namespace defined at ns1 body, not in envelope. 因此,我从Wireshark那里获取了来自其他DLNA服务器的xml,并发现它们全部返回了另一个xml,并且在ns1主体中定义了命名空间,而不是在信封中。 This is sample correct lines, that all devices accepting well: 这是正确的示例行,所有设备都接受:

<?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>

So the "ContentDirectory" xmlns just moved into a block from header. 因此,“ ContentDirectory” xmlns刚刚从标头移入了一个块。 Both xmls are syntactically correct. 这两个xml在语法上都是正确的。

Some guys also faced same problem: 有些人也面临着同样的问题:

Problem with WSDL WSDL问题

change soap prefixes in php 更改php中的肥皂前缀

Soap Response Namespace issue 肥皂响应命名空间问题

SoapServer maps functions incorectly when the wsdl messages have the same part name 当wsdl消息具有相同的部件名称时,SoapServer映射功能不正确

PHP Soap Server response formatting PHP Soap Server响应格式

After 2-days of research, I figured out this workaround, to change binding from document to rpc method: 经过2天的研究,我找到了解决方法,可以将绑定从文档更改为rpc方法:

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

but when I doing this, the php script just crashes [somewhere inside of zend engine?], so I have a line in access.log mentioned 500 error happened, but it does not shown in error.log - the file keeps empty (of course, all the others 500 errors goes to error.log pretty well). 但是当我这样做时,php脚本只是崩溃了[zend引擎内部的某个地方?],所以我在access.log中有一行提到发生了500个错误,但是在error.log中没有显示-文件保持空白(当然,其他所有500个错误都会很好地进入error.log)。

As it is too big, I have uploaded WSDL file: http://pastebin.com/ZNG4DqAn 由于太大,我上传了WSDL文件: http : //pastebin.com/ZNG4DqAn

Is there something else, that I can try to workaround this trouble? 还有其他可以解决此问题的方法吗?

Remember, that TV handles this xml syntax completely correct, and everything works very well, but probably android phones does other xml parser that requires namespace in that place? 记住,电视可以完全正确地处理此xml语法,并且一切工作都很好,但是可能android手机是否需要其他需要名称空间的xml解析器? Just right now I am already ready to do preg_replaces() to move that damned xmlns to the correct place :), but I am thinking this is not a path for the Jedies :) 现在,我已经准备好进行preg_replaces()来将该死的xmlns移动到正确的位置:),但是我认为这不是Jedies的路径:)

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

Finally I will not become Jedi, I did manual replacement and it works. 最终,我不再成为绝地武士,而是进行了手动替换,并且可以正常工作。

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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM