I'm fairly new to the SOAP and WSDL world. What do I have to do, to make sure that the namespace will always be in the return-element?
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://someurl.com">
<SOAP-ENV:Body>
<ns1:sayHelloResponse>
<return>Say Hello Kelvin</return>
</ns1:sayHelloResponse>
</SOAP-ENV:Body>
</SOAP-ENV:Envelope>
What I want is:
<ns1:sayHelloResponse>
<ns1:return>Say Hello Kelvin</ns1:return>
</ns1:sayHelloResponse>
I'm using PHP and the Zend Framework. The WSDL gets generated by Zend_Soap_AutoDiscovery. This shouldn't be a barrier though, because I will modify the output of it anyways.
Thanks for your help.
After taking a break for a while, I approached the problem once again. This time though, I stumbled upon this nice article (credits to my former co-worker Mike). If the attribute elementFormDefault isn't declared in the schema tag, unqualified is assumed as its value. By giving it the value "qualified" the following will happen:
But if you add elementFormDefault="qualified" to all of the schemas in the document/literal wrapped WSDL, then all elements in the messages would be qualified with their parent's namespace.
In general, you do not want to use elementFormDefault="qualified" because it bloats the messages, but a year or more ago there were interoperability issues between various vendors, and setting this attribute sometimes fixed the problems.
Even though I wasn't using document/literal, I wanted to try it out. I added the attribute to my schema tag and made a request to a different call. Here's the response I got:
<ns1:getUserResponse>
<return>
<ns1:firstname>First</ns1:firstname>
<ns1:lastname>Last</ns1:lastname>
</return>
</ns1:getUserResponse>
As you can see, the child elements of the "return"-element got the namespace prefixed. At this point I got really excited, because I finally got closer to where I wanted to be. Unfortunately, the return element didn't have the namespace prefixed. I tried the earlier call (see question post) again, but the response was the same as before.
I couldn't spend more time on this issue. It was just a prototype after all. That's why I decided to hook into Zend_Soap_Server's handle function, to modify the response before outputting it.
class Custom_Soap_Server extends Zend_Soap_Server
{
public function __construct($wsdl = null, array $options = null)
{
parent::__construct($wsdl, $options);
// Response of handle will always be returned
$this->setReturnResponse(true);
}
public function handle($request = null)
{
$response = parent::handle($request);
echo str_replace(array('<return>', '</return>'), array('<ns1:return>', '</ns1:return>'), $response);
return;
}
}
To be honest, it's a nasty hack. I'm always assuming that there's just one namespace. The replace function could be written much better. But it was for a prototype after all and this was my first thought to make it work.
After using the new custom class instead of Zend_Soap_Server, all of the return elements had ns1 prefixed to them.