gsoap入门:解决axis2服务器返回错误:com.ctc.wstx.exc.WstxParsingException: Undeclared namespace prefix "ns1"
2016-08-13 12:51
471 查看
我们的项目中webservice服务器已经搭建好,基于用axis2提供名为FaceDbService的人脸识别服务。现在的任务是用gosap开发C++版本的客户端,所以最近在尝试用gsoap生成的c++代码来调用webservice.
关于生成gsoap C++客户端代码及编译,参见我的前一篇博客《gsoap入门:C/C++代码生成及编译》。
仔细查看request xml输出发现这个xml居然没有
试了各种 关键字在google/baidu上搜索,最后用”gsoap not SOAP-ENV:Envelope”用google在stackoverflow上找到一个类似的情况《Breaking changes in gsoap (updating version from 2.8.8 to 2.8.16)》
其中一个答案,给了我提醒 :
貌似是因为soap.namespaces变量为NULL造成的,再运行程序证实了这个猜测,soap.namespaces果然为NULL;
于是尝试在soap对象创建后,添加如下代码,问题解决。
于是想到跟踪soap对象的代码,看看namespaces变量是怎么被初始化的。找到了这里(
因为我在用gsoapcpp2生成gosap C++客户端代码的时候使用了
再进一步研究gsoap的手册关于编译参数的控制参见《9.11 Library Build Flags》,找到
这里说明,如果使用了
到此,问题基本算是搞清楚了,导致soap请求数据格式错误的直接原因是soap初始化时没有指定namespace。
从上面的分析来看,解决这个问题,有两个方案:
这个方法最简单,但在
这个方法也不复杂,只是添加一行代码,前面的测试代码修改如下:
关于生成gsoap C++客户端代码及编译,参见我的前一篇博客《gsoap入门:C/C++代码生成及编译》。
测试代码
下面是测试代码#include <sstream> #include "FaceDbServiceSoap11Binding.nsmap" #include "file_utilits.h" #include "stdlib.h" #include "plugin.h" using namespace facedbservice; int main(int argc, char * argv[]) { struct soap soap; // 对象初始化 soap_init(&soap); // 注册plugin插件,用于显示request/response xml文本用于调试 soap_register_plugin(&soap, plugin); // RPC调用参数对象 _ns1__sdk_USCOREdetectFace param; // RPC返回对象 _ns1__sdk_USCOREdetectFaceResponse ret; // 加载一张图像数据到内存(字节数组std::vector<uint8_t>) auto img_file= gdface::load_binary_file("d:\\tmp\\he049.jpg"); // 将字节数组转为xsd__base64Binary对象,并设置为imgData参数 xsd__base64Binary b; b.soap = &soap; b.__ptr = img_file.data(); b.__size = img_file.size(); param.imgData = &b; // 执行soap调用detectFace soap_call___ns1__sdk_USCOREdetectFace(&soap,"http://gdface.wicp.net:15865/axis2/services/FaceDbService",nullptr, ¶m,ret); // 检查错误 if (soap.error!= SOAP_OK) { // 显示错误信息 soap_stream_fault(&soap, std::cerr); }else { // 调用成功则输出返回的数据 for (auto code : ret.return_) { std::printf("soap err,errcode = (%d,%d,%d,%d)\n", *(code->pos->left), *(code->pos->top), *(code->pos->width), *(code->pos->height)); } } soap_done(&soap); }
错误信息
程序执行时出错了://///////plugin插件输出的 request xml/////////////////////////////////// POST /axis2/services/FaceDbService HTTP/1.1 Host: 192.168.1.18:8080 User-Agent: gSOAP/2.8 Content-Type: text/xml; charset=utf-8 Content-Length: 8583 Connection: close SOAPAction: "urn:sdk_detectFace" <?xml version="1.0" encoding="UTF-8"?> <ns:sdk_detectFace><ns:imgData> //...图像数据 </ns:imgData></ns:sdk_detectFace> HTTP/1.1 500 Int ernal Server Error Server: Apache-Coyote/1.1 Content-Type: text/xml;charset=utf-8 Transfer-Encoding: chunked Date: Sat, 13 Aug 2016 02:55:08 GMT Connection: close /////////plugin插件输出的 response xml/////////////////////////////////// 205 <?xml version='1.0' encoding='utf-8'?><soapenv:Envelope xmlns:soapenv="http://sc hemas.xmlsoap.org/soap/envelope/"><soapenv:Header xmlns:wsa="http://www.w3.org/2 005/08/addressing"><wsa:Action>http://www.w3.org/2005/08/addressing/soap/fault</ wsa:Action></soapenv:Header><soapenv:Body><soapenv:Fault><faultcode></faultcode> <faultstring>com.ctc.wstx.exc.WstxParsingException: Undeclared namespace prefix "ns1" at [row,col {unknown-source}]: [2,19]</faultstring><detail /></soapenv:Fault></ soapenv:Body></soapenv:Envelope> ///////// 上面代码中soap_stream_fault()输出/////// Error 500 fault at source[no subcode] "Error 500: HTTP 500 Internal Server Error" Detail: [no detail]
原因分析
总是返回Undeclared namespace prefix "ns"。
仔细查看request xml输出发现这个xml居然没有
SOAP-ENV:Envelopetag,这不是个标准的SOAP格式啊。
试了各种 关键字在google/baidu上搜索,最后用”gsoap not SOAP-ENV:Envelope”用google在stackoverflow上找到一个类似的情况《Breaking changes in gsoap (updating version from 2.8.8 to 2.8.16)》
其中一个答案,给了我提醒 :
貌似是因为soap.namespaces变量为NULL造成的,再运行程序证实了这个猜测,soap.namespaces果然为NULL;
于是尝试在soap对象创建后,添加如下代码,问题解决。
if(!soap->namespaces) soap->namespaces=namespaces; // namespaces变量定义在#include "FaceDbServiceSoap11Binding.nsmap"
解决方案
虽然这样解决了问题,但还是不知道为什么呀,网上其他的教程中没有提到要手工设置soap.namespaces变量呀。
于是想到跟踪soap对象的代码,看看namespaces变量是怎么被初始化的。找到了这里(
soap_versioning(soap_init)(struct soap *soap, soap_mode imode, soap_mode omode)函数中),看到这里瞬间明白了。:
因为我在用gsoapcpp2生成gosap C++客户端代码的时候使用了
-DWITH_NONAMESPACES编译stdsoap2.cpp文件,所以这里初始化soap对象时就将namespaces指针赋值为NULL。
再进一步研究gsoap的手册关于编译参数的控制参见《9.11 Library Build Flags》,找到
WITH_NONAMESPACES的说明(下图红框部分)
这里说明,如果使用了
-DWITH_NONAMESPACES定义,就必须显式的使用
soap_set_namespaces为soap对象指定namespace。
到此,问题基本算是搞清楚了,导致soap请求数据格式错误的直接原因是soap初始化时没有指定namespace。
从上面的分析来看,解决这个问题,有两个方案:
解决方案1
去掉编译stdsoap2.cpp文件设置的
-DWITH_NONAMESPACES宏定义
这个方法最简单,但在
multi-client and multi-server builds模式下并不适合,因为这种模式下必须使用
-DWITH_NONAMESPACES宏定义,参见《9.1 soapcpp2 Options》
解决方案2
在soap对象初始化后用soap_set_namespaces函数为soap对象指定namespace。
这个方法也不复杂,只是添加一行代码,前面的测试代码修改如下:
#include <sstream> #include "FaceDbServiceSoap11Binding.nsmap" #include "file_utilits.h" #include "stdlib.h" #include "plugin.h" using namespace facedbservice; int main(int argc, char * argv[]) { soap soap; // 对象初始化 // soap_init(&soap);//C++下不需要,因为soap的构造函数已经执行过soap_init // 设置namespaces // namespaces变量定义在#include "FaceDbServiceSoap11Binding.nsmap" soap_set_namespaces(&soap, namespaces); // 下面省略的代码与以前相同 ..... //soap_done(&soap);//C++下不需要,因为soap的析构函数会执行soap_done }
相关文章推荐
- com.ctc.wstx.exc.WstxParsingException: Illegal processing instruction target ("xml"); xml (case insensitive) is reserved by the
- SOAP Exception:com.ctc.wstx.exc.WstxParsingException: Unexpected close tag ; expected .
- SOAP Exception:com.ctc.wstx.exc.WstxParsingException: Unexpected close tag ; expected .
- “System.ServiceModel.DomainServices.Client.DomainOperationException:查询"XXX"load操作失败,远程服务器返回了错误:NoFound.……”解决方法
- "对COM 组件的调用返回了错误 HRESULT E_FAIL"的解决方法
- BeanDefinitionParsingException: Configuration problem: Unable to locate Spring NamespaceHandler错误的解决方法
- 错误“Unexpected namespace prefix "xmlns" found for tag LinearLayout”的解决方法(转)
- [转]C# post数据时 出现如下错误: System.Net.WebException: 远程服务器返回错误: (417) Expectation Failed 的解决办法
- C# post数据时 出现如下错误: System.Net.WebException: 远程服务器返回错误: (417) Expectation Failed 的解决办法
- 错误“Unexpected namespace prefix "xmlns" found for tag LinearLayout”的解决方法(转)
- "对COM 组件的调用返回了错误 HRESULT E_FAIL"的解决方法
- 错误“Unexpected namespace prefix "xmlns" found for tag LinearLayout”的解决方法
- 错误“Unexpected namespace prefix "xmlns" found for tag LinearLayout”的解决方法
- AXIS2:com.ctc.wstx.exc.WstxEOFException错误
- 错误“Unexpected namespace prefix "xmlns" found for tag LinearLayout”的解决方法
- C# post数据时 出现如下错误: System.Net.WebException: 远程服务器返回错误: (417) Expectation Failed 的解决办法
- 错误“Unexpected namespace prefix "xmlns" found for tag LinearLayout”的解决方法
- "对COM 组件的调用返回了错误 HRESULT E_FAIL"的解决方法
- gsoap入门:获取服务器(axis2)端的异常(exception)对象
- 错误“Unexpected namespace prefix "xmlns" found for tag LinearLayout”的解决方法