利用C++调用天气webservice-gSOAP方法
2016-02-19 11:28
609 查看
首先需要下载一个gSOAP工具包 下载路径为:https://sourceforge.net/projects/gsoap2/
至于有关于gSOAP的一些用法和包含的文件的说明可从官网查看:http://www.genivia.com/dev.html。
下载和使用gSOAP生成一些库文件提供给C++工程使用:
解压gsoap文件夹,此处解压的是gsoap-2.8文件夹,放在E盘
打开E:\gsoap-2.8\gsoap\bin\win32文件夹
创建一个文件名为wsmap.dat 以文本形式写入 xsd__string = | std::wstring | wchar_t* ,此文件用来将SOAP/XML中的string转换成std::wstrin或wchar_t*,这样能更好地支持中文
cmd命令行方式到 cd E:\gsoap-2.8\gsoap\bin\win32文件夹,调用wdsl2h.exe文件生成头文件接口定义,命令为
wdsl2h -o WebService.h -n WS -t wsmap.dat http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL
WebService.h为头文件名称,可自选
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL 为需要访问的webservice的WSDL文件地址
-o 文件名,指定输出头文件
-n 名空间前缀 代替默认的ns
-c 产生纯C代码,否则是C++代码
-s 不要使用STL代码
-t 文件名,指定type map文件,默认为typemap.dat
-e 禁止为enum成员加上名空间前缀
5.输入soapcpp2 -C WebService.h -i -L -I E:\gsoap-2.8\gsoap\import
-C 仅生成客户端代码
-S 仅生成服务器端代码
-L 不要产生soapClientLib.c和soapServerLib.c文件
-c 产生纯C代码,否则是C++代码(与头文件有关)
-I 指定import路径(此项是必要的,因前面为指定-s)
-x 不要产生XML示例文件
-i生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)。
6.将生成的soapH.h、soapStub.h、soapWeatherWebServiceSoapProxy.h、WeatherWebService.h、soapWeatherWebServiceSoapProxy.cpp、soapC.cpp、WeatherWebServiceSoap.nsmap E:\gsoap-2.8\gsoap文件夹下的stdsoap2.h、stdsoap2.cpp拷贝到要使用的工程目录下
首先声明阶段include 要载入的头文件和命名空间,要引入.nsmap文件是因为此为要使用的webservice命名空间
上面使用了vector头文件是为了能够输出信息,天气webservice中所有返回数据都是vector类型下面我们会讲到
初始化的时候使用webservice的访问地址,不需要添加WSDL文件后缀。
初始化getSupportCity对象,getSupport对象的属性可从http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getSupportCity 中查看为
_WS1__getSupportCityResponse response; proxy.getSupportCity(&weatherCity, response);wcout.imbue(locale("chs"));for (int i = 0; i < response.getSupportCityResult->string.size(); i++) wcout << response.getSupportCityResult->string[i] << endl;
在这个里面可以看到我们输出是使用的是wcout 而不是 cout 因为 这个是getSupportCityResult这个成员属性是一个自定义的属性,用来保存的数据都是以wchar形式保存的
至于为什么会是wchar是因为原来我们使用的那一段文字 xsd__string = | std::wstring | wchar_t* 这将string类型转换为wstring 或 wchar。这样可以保证中文文字的合理显示,否则会出现乱码。
出现乱码的原因:HTML和XML中通用的编码格式是UTF-8,而代码一般是使用Unicode。但是如果webservice是使用C++编写的,则不需要wchar也可以使用。而使用的如果是C#、Java之类的编写的webservice则不使用wchar进行传参就会造成乱码。
这里需要说明的是一般的默认显示是_ns1_getSupportCity,而我显示的是_WS1_getSupportCity原因是因为 wdsl2h -o WebService.h -n WS -t wsmap.dat http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL这条命令中我输出了一个-n WS将名称前缀换掉了
从_WS1_getSupportCityResponse的定义知道getSupportCityResult这个成员变量是自定义的一个属性
soapStub.h
接下来我们先输出一下运行结果
这是一部分,不是全部,但是毫无疑问我们输出成功了。
然后我们再来调用天气接口进行查看天气。首先我们查看WeatherbyCityName对象的属性,也是从 http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getWeatherbyCityName 中查看的
String(0) 到 String(4):省份,城市,城市代码,城市图片名称,最后更新时间。String(5) 到 String(11):当天的 气温,概况,风向和风力,天气趋势开始图片名称(以下称:图标一),天气趋势结束图片名称(以下称:图标二),现在的天气实况,天气和生活指数。String(12) 到 String(16):第二天的 气温,概况,风向和风力,图标一,图标二。String(17) 到 String(21):第三天的 气温,概况,风向和风力,图标一,图标二。String(22) 被查询的城市或地区的介绍
由此可知,如果我们上面的City不变,应该显示的是上海,另外此输出应该是一个有23个元素的wstring对象.
我也是初次使用C++调用webService,如果有什么更好的方法希望大家多交流
至于有关于gSOAP的一些用法和包含的文件的说明可从官网查看:http://www.genivia.com/dev.html。
下载和使用gSOAP生成一些库文件提供给C++工程使用:
解压gsoap文件夹,此处解压的是gsoap-2.8文件夹,放在E盘打开E:\gsoap-2.8\gsoap\bin\win32文件夹
创建一个文件名为wsmap.dat 以文本形式写入 xsd__string = | std::wstring | wchar_t* ,此文件用来将SOAP/XML中的string转换成std::wstrin或wchar_t*,这样能更好地支持中文
cmd命令行方式到 cd E:\gsoap-2.8\gsoap\bin\win32文件夹,调用wdsl2h.exe文件生成头文件接口定义,命令为
wdsl2h -o WebService.h -n WS -t wsmap.dat http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL
WebService.h为头文件名称,可自选
http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL 为需要访问的webservice的WSDL文件地址
-o 文件名,指定输出头文件
-n 名空间前缀 代替默认的ns
-c 产生纯C代码,否则是C++代码
-s 不要使用STL代码
-t 文件名,指定type map文件,默认为typemap.dat
-e 禁止为enum成员加上名空间前缀
5.输入soapcpp2 -C WebService.h -i -L -I E:\gsoap-2.8\gsoap\import
-C 仅生成客户端代码
-S 仅生成服务器端代码
-L 不要产生soapClientLib.c和soapServerLib.c文件
-c 产生纯C代码,否则是C++代码(与头文件有关)
-I 指定import路径(此项是必要的,因前面为指定-s)
-x 不要产生XML示例文件
-i生成C++包装,客户端为xxxxProxy.h(.cpp),服务器端为xxxxService.h(.cpp)。
6.将生成的soapH.h、soapStub.h、soapWeatherWebServiceSoapProxy.h、WeatherWebService.h、soapWeatherWebServiceSoapProxy.cpp、soapC.cpp、WeatherWebServiceSoap.nsmap E:\gsoap-2.8\gsoap文件夹下的stdsoap2.h、stdsoap2.cpp拷贝到要使用的工程目录下
下面贴入代码段:
首先声明阶段include 要载入的头文件和命名空间,要引入.nsmap文件是因为此为要使用的webservice命名空间
<pre name="code" class="cpp">#include <iostream> #include <vector> #include <string> #include <locale> //载入webservice的头文件和命名空间 #include "soapWeatherWebServiceSoapProxy.h" #include "WeatherWebServiceSoap.nsmap"using namespace std;
上面使用了vector头文件是为了能够输出信息,天气webservice中所有返回数据都是vector类型下面我们会讲到
接下来我们初始化webservice
//初始化webservice对象 WeatherWebServiceSoapProxy proxy("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx"); //城市名称,可为空,为空则显示所有的城市对应的编码 string City(""); int len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)City.c_str(), -1, NULL, 0); wchar_t * wszutf8 = new wchar_t[len + 1]; memset(wszutf8, 0, len * 2 + 2); MultiByteToWideChar(CP_ACP, 0, (LPCSTR)City.c_str(), -1, (LPWSTR)wszutf8, len); //设置编码格式 //soap_set_mode(&proxy, SOAP_C_MBSTRING);
初始化的时候使用webservice的访问地址,不需要添加WSDL文件后缀。
初始化getSupportCity对象,getSupport对象的属性可从http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getSupportCity 中查看为
查询本天气预报Web Services支持的国内外城市或地区信息
输入参数:byProvinceName = 指定的洲或国内的省份,若为ALL或空则表示返回全部城市;返回数据:一个一维字符串数组 String(),结构为:城市名称(城市代码)。然后我们创建一个返回Support City信息的类对象
<pre name="code" class="cpp"> //初始化getSupportCity对象 _WS1__getSupportCity weatherCity; weatherCity.soap = &proxy; weatherCity.byProvinceName = wszutf8;
_WS1__getSupportCityResponse response; proxy.getSupportCity(&weatherCity, response);wcout.imbue(locale("chs"));for (int i = 0; i < response.getSupportCityResult->string.size(); i++) wcout << response.getSupportCityResult->string[i] << endl;
在这个里面可以看到我们输出是使用的是wcout 而不是 cout 因为 这个是getSupportCityResult这个成员属性是一个自定义的属性,用来保存的数据都是以wchar形式保存的
至于为什么会是wchar是因为原来我们使用的那一段文字 xsd__string = | std::wstring | wchar_t* 这将string类型转换为wstring 或 wchar。这样可以保证中文文字的合理显示,否则会出现乱码。
出现乱码的原因:HTML和XML中通用的编码格式是UTF-8,而代码一般是使用Unicode。但是如果webservice是使用C++编写的,则不需要wchar也可以使用。而使用的如果是C#、Java之类的编写的webservice则不使用wchar进行传参就会造成乱码。
这里需要说明的是一般的默认显示是_ns1_getSupportCity,而我显示的是_WS1_getSupportCity原因是因为 wdsl2h -o WebService.h -n WS -t wsmap.dat http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL这条命令中我输出了一个-n WS将名称前缀换掉了
从_WS1_getSupportCityResponse的定义知道getSupportCityResult这个成员变量是自定义的一个属性
soapStub.h
/* WeatherWebService.h:170 */ #ifndef SOAP_TYPE__WS1__getSupportCityResponse #define SOAP_TYPE__WS1__getSupportCityResponse (14) /* WS1:getSupportCityResponse complex type: */ class SOAP_CMAC _WS1__getSupportCityResponse { public: WS1__ArrayOfString *getSupportCityResult; /* SOAP 1.2 RPC return element (when namespace qualified) */ /* optional element of XSD type WS1:ArrayOfString */ struct soap *soap; /* transient (not serialized) */ public: /// Return the unique type ID value SOAP_TYPE__WS1__getSupportCityResponse (14) virtual int soap_type(void) const { return 14; } /// Set object's data members to default values virtual void soap_default(struct soap*); /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures virtual void soap_serialize(struct soap*) const; /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK virtual int soap_put(struct soap*, const char *tag, const char *type) const; /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const; /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error virtual void *soap_get(struct soap*, const char *tag, const char *type); /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error virtual void *soap_in(struct soap*, const char *tag, const char *type); /// Return a new object of type _WS1__getSupportCityResponse, default initialized and not managed by a soap context virtual _WS1__getSupportCityResponse *soap_alloc(void) const { return SOAP_NEW(_WS1__getSupportCityResponse); } _WS1__getSupportCityResponse() { _WS1__getSupportCityResponse::soap_default(NULL); } virtual ~_WS1__getSupportCityResponse() { } friend _WS1__getSupportCityResponse *soap_instantiate__WS1__getSupportCityResponse(struct soap*, int, const char*, const char*, size_t*); }; #endif此自定义属性为WS1_ArrayOfString 类型,此类型的定义可以看出为什么要使用wchar类型
/* WeatherWebService.h:164 */ #ifndef SOAP_TYPE_WS1__ArrayOfString #define SOAP_TYPE_WS1__ArrayOfString (12) /* WS1:ArrayOfString complex type: */ class SOAP_CMAC WS1__ArrayOfString { public: std::vector<std::wstring> string; /* optional element of XSD type xsd:string */ struct soap *soap; /* transient (not serialized) */ public: /// Return the unique type ID value SOAP_TYPE_WS1__ArrayOfString (12) virtual int soap_type(void) const { return 12; } /// Set object's data members to default values virtual void soap_default(struct soap*); /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures virtual void soap_serialize(struct soap*) const; /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK virtual int soap_put(struct soap*, const char *tag, const char *type) const; /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const; /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error virtual void *soap_get(struct soap*, const char *tag, const char *type); /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error virtual void *soap_in(struct soap*, const char *tag, const char *type); /// Return a new object of type WS1__ArrayOfString, default initialized and not managed by a soap context virtual WS1__ArrayOfString *soap_alloc(void) const { return SOAP_NEW(WS1__ArrayOfString); } WS1__ArrayOfString() { WS1__ArrayOfString::soap_default(NULL); } virtual ~WS1__ArrayOfString() { } friend WS1__ArrayOfString *soap_instantiate_WS1__ArrayOfString(struct soap*, int, const char*, const char*, size_t*); }; #endif定义的string其实是一个vector<wstring>类型的,这也是为什么我要使用vector头文件和 char与wchar转换的原因。
接下来我们先输出一下运行结果
这是一部分,不是全部,但是毫无疑问我们输出成功了。
然后我们再来调用天气接口进行查看天气。首先我们查看WeatherbyCityName对象的属性,也是从 http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getWeatherbyCityName 中查看的
根据城市或地区名称查询获得未来三天内天气情况、现在的天气实况、天气和生活指数
调用方法如下:输入参数:theCityName = 城市中文名称(国外城市可用英文)或城市代码(不输入默认为上海市),如:上海 或 58367,如有城市名称重复请使用城市代码查询(可通过 getSupportCity 或 getSupportDataSet 获得);返回数据: 一个一维数组 String(22),共有23个元素。String(0) 到 String(4):省份,城市,城市代码,城市图片名称,最后更新时间。String(5) 到 String(11):当天的 气温,概况,风向和风力,天气趋势开始图片名称(以下称:图标一),天气趋势结束图片名称(以下称:图标二),现在的天气实况,天气和生活指数。String(12) 到 String(16):第二天的 气温,概况,风向和风力,图标一,图标二。String(17) 到 String(21):第三天的 气温,概况,风向和风力,图标一,图标二。String(22) 被查询的城市或地区的介绍
由此可知,如果我们上面的City不变,应该显示的是上海,另外此输出应该是一个有23个元素的wstring对象.
_WS1__getWeatherbyCityName weatherName; weatherName.soap = &proxy; weatherName.theCityName = wszutf8; _WS1__getWeatherbyCityNameResponse weatherResponse; proxy.getWeatherbyCityName(&weatherName, weatherResponse); for (int i = 0; i < weatherResponse.getWeatherbyCityNameResult->string.size(); i++) wcout << weatherResponse.getWeatherbyCityNameResult->string[i] << endl;原理与上面获得城市信息相同,就不多说了,下面贴出运行结果
我也是初次使用C++调用webService,如果有什么更好的方法希望大家多交流
相关文章推荐
- 自定义 C++ 中的 range() 函数
- C++ template —— 模板与继承(八)
- c++ 在windows下获取时间和计算时间差的几种方法总结
- C++标准模板库
- C语言单链表实现19个功能完全详解
- 值得推荐的C/C++框架和库 (真的很强大)
- C++ Primer Plus 札记(二)指针
- Java与C/C++比较——对象引用方面
- 《STL源码剖析》之 ROUND_UP()实现原理详解
- c++之动态库和静态库的区别
- C++中调用C函数库
- c++函数模板声明与定义相分离
- C语言深度解剖读书笔记
- c++ 设计模式4 (Strategy)
- C与C++中使用带默认值的参数
- Typical memory leak (C++中典型的内存泄露)
- 纯C语言实现简单继承机制
- 转:C语言面试题大汇总 (图像处理方向)
- &#10084;&#65039;C++的继承
- &#10084;&#65039;C++基础语法