前些天给一个项目写测试工具,这个项目用的是SOAP协议作为通讯协议,服务端是用的Apache CXF框架写的webservice。而我习惯用C++写程序,所以用gsoap的开发包来开发SOAP的协议层。以前用的是gsoap 2.7.15,一直没有出过问题。但这次发现网上已经出了2.7.17版本了。索性下来试下。一切都按以前的流程自动生成客户端代理的代码。但在联调时,CXF的服务端一直报无法解析。我仔细查看了gsoap发达的SOAP数据包,发现里面竟然变成这样:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns1="http://www.abcd.com/wsdl">
<SOAP-ENV:Body>
<ns1:EventRequest version="">
<Client>
<TerminalAddress type=""></TerminalAddress>
<TargetCode key=""></TargetCode>
<TargetCode key=""></TargetCode>
</Client>
<Event class="" detail="">
</Event>
<Content assetID="">
<ContentLocation></ContentLocation>
<NPT scale=""></NPT>
</Content>
.......
这只是一部分截取。可以发现只有第一层元素有命名空间前缀(<ns1:EventRequest version="">),但里面的其它层都没有了前缀,而且也没有默认的命名空间,当然无法解析了。但WSDL的文件定义已经用了document/literal的自说明格式,说明一定是gsoap生成的SOAP错误了。
我又用2.7.15版本生成soap根文件,片段如下:
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope
xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:ns1="http://www.abcd.com/wsdl">
<SOAP-ENV:Body>
<ns1:EventRequest version="">
<ns1:Client>
<ns1:TerminalAddress type=""></ns1:TerminalAddress>
<ns1:TargetCode key=""></ns1:TargetCode>
</ns1:Client>
<ns1:Event class="" detail="">
</ns1:Event>
<ns1:Content assetID="">
<ns1:ContentLocation></ns1:ContentLocation>
<ns1:NPT scale=""></ns1:NPT>
</ns1:Content>
......
前缀已经加上了。好在gsoap的开发包提供了wsdl2h和soapcpp2的工具源码,我大概研究了一下。如果要利用2.7.17生成下面的SOAP,可以增加一个参数,我看下了文档,对这个参数的描述是这样的:
-z2 compatibilitywith2.7.15:qualifyelement/attributereferencedmembers。还是为了兼容2.7.15。感觉作者是有意要修改为目前这种方式的,但像CXF这样的解析器缺无法解析。如果要强制增加空间定义可以在定义WSDL时,增加xsd:schema 属性。
例如:
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="qualified" targetNamespace="http://www.abcd.com/wsdl" xmlns="http://www.abcd.com/wsdl">
在使用gsoap 2.7.17生成的SOAP包与Apache CXF进行通信时遇到解析错误,原因是gsoap生成的XML中深层元素缺失命名空间前缀。通过对比2.7.15版本,发现可通过增加参数`-z2`来恢复兼容性。此外,可以在WSDL定义中设置`elementFormDefault`和`attributeFormDefault`为`qualified`来解决此问题。
6371





