简体   繁体   中英

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. 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:

<?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. But most of my DLNA devices won't accept this answer (but Toshiba TV works very well with it). 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. 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. Both xmls are syntactically correct.

Some guys also faced same problem:

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

After 2-days of research, I figured out this workaround, to change binding from document to rpc method:

<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).

As it is too big, I have uploaded WSDL file: 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? 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 :)

My environment: 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;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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