문제

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.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top