利用C++調用天氣webservice-gSOAP方法

首先須要下載一個gSOAP工具包 下載路徑爲:https://sourceforge.NET/projects/gsoap2/html

至於有關於gSOAP的一些用法和包含的文件的說明可從官網查看:http://www.genivia.com/dev.html。java

 

下載和使用gSOAP生成一些庫文件提供給C++工程使用:

  1. 解壓gsoap文件夾,此處解壓的是gsoap-2.8文件夾,放在E盤
  2. 打開E:\gsoap-2.8\gsoap\bin\win32文件夾
  3. 建立一個文件名爲wsmap.dat 以文本形式寫入  xsd__string = | std::wstring | wchar_t*   ,此文件用來將SOAP/XML中的string轉換成std::wstrin或wchar_t*,這樣能更好地支持中文
  4. 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爲頭文件名稱,可自選ios

        http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?WSDL 爲須要訪問的webservice的WSDL文件地址

web

  •     -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命名空間

 

[html]  view plain  copy
 
  1. <pre name="code" class="cpp">#include <iostream>  
  2. #include <vector>  
  3. #include <string>  
  4. #include <locale>   
  5.   
  6. //載入webservice的頭文件和命名空間  
  7. #include "soapWeatherWebServiceSoapProxy.h"     
  8. #include "WeatherWebServiceSoap.nsmap"  

using namespace std;ide

 

 

上面使用了vector頭文件是爲了可以輸出信息,天氣webservice中全部返回數據都是vector類型下面咱們會講到工具

 

 

接下來咱們初始化webservice

 

[cpp]  view plain  copy
 
  1.        //初始化webservice對象  
  2. WeatherWebServiceSoapProxy proxy("http://www.webxml.com.cn/WebServices/WeatherWebService.asmx");  
  3.   
  4. //城市名稱,可爲空,爲空則顯示全部的城市對應的編碼  
  5. string City("");  
  6. int len = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)City.c_str(), -1, NULL, 0);  
  7. wchar_t * wszutf8 = new wchar_t[len + 1];  
  8. memset(wszutf8, 0, len * 2 + 2);  
  9. MultiByteToWideChar(CP_ACP, 0, (LPCSTR)City.c_str(), -1, (LPWSTR)wszutf8, len);  
  10.   
  11.   
  12. //設置編碼格式  
  13. //soap_set_mode(&proxy, SOAP_C_MBSTRING);  
  14.   
  15.          


初始化的時候使用webservice的訪問地址,不須要添加WSDL文件後綴。編碼

 

 

 

初始化getSupportCity對象,getSupport對象的屬性可從http://www.webxml.com.cn/WebServices/WeatherWebService.asmx?op=getSupportCity 中查看爲spa

 

查詢本天氣預報Web Services支持的國內外城市或地區信息

 

輸入參數:byProvinceName = 指定的洲或國內的省份,若爲ALL或空則表示返回所有城市;返回數據:一個一維字符串數組 String(),結構爲:城市名稱(城市代碼)。

而後咱們建立一個返回Support City信息的類對象

 

[cpp]  view plain  copy
 
  1. <pre name="code" class="cpp">        //初始化getSupportCity對象  
  2.        _WS1__getSupportCity weatherCity;  
  3.     weatherCity.soap = &proxy;  
  4.     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

 

[cpp]  view plain  copy
 
  1. /* WeatherWebService.h:170 */  
  2. #ifndef SOAP_TYPE__WS1__getSupportCityResponse  
  3. #define SOAP_TYPE__WS1__getSupportCityResponse (14)  
  4. /* WS1:getSupportCityResponse complex type: */  
  5. class SOAP_CMAC _WS1__getSupportCityResponse  
  6. {  
  7. public:  
  8.     WS1__ArrayOfString *getSupportCityResult;   /* SOAP 1.2 RPC return element (when namespace qualified) */    /* optional element of XSD type WS1:ArrayOfString */  
  9.     struct soap *soap;  /* transient (not serialized) */  
  10. public:  
  11.     /// Return the unique type ID value SOAP_TYPE__WS1__getSupportCityResponse (14)  
  12.     virtual int soap_type(void) const { return 14; }  
  13.     /// Set object's data members to default values  
  14.     virtual void soap_default(struct soap*);  
  15.     /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures  
  16.     virtual void soap_serialize(struct soap*) const;  
  17.     /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK  
  18.     virtual int soap_put(struct soap*, const char *tag, const char *type) const;  
  19.     /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK  
  20.     virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const;  
  21.     /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error  
  22.     virtual void *soap_get(struct soap*, const char *tag, const char *type);  
  23.     /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error  
  24.     virtual void *soap_in(struct soap*, const char *tag, const char *type);  
  25.     /// Return a new object of type _WS1__getSupportCityResponse, default initialized and not managed by a soap context  
  26.     virtual _WS1__getSupportCityResponse *soap_alloc(void) const { return SOAP_NEW(_WS1__getSupportCityResponse); }  
  27.              _WS1__getSupportCityResponse() { _WS1__getSupportCityResponse::soap_default(NULL); }  
  28.     virtual ~_WS1__getSupportCityResponse() { }  
  29.     friend _WS1__getSupportCityResponse *soap_instantiate__WS1__getSupportCityResponse(struct soap*, int, const char*, const char*, size_t*);  
  30. };  
  31. #endif  

此自定義屬性爲WS1_ArrayOfString 類型,此類型的定義能夠看出爲何要使用wchar類型

 

 

[cpp]  view plain  copy
 
  1. /* WeatherWebService.h:164 */  
  2. #ifndef SOAP_TYPE_WS1__ArrayOfString  
  3. #define SOAP_TYPE_WS1__ArrayOfString (12)  
  4. /* WS1:ArrayOfString complex type: */  
  5. class SOAP_CMAC WS1__ArrayOfString  
  6. {  
  7. public:  
  8.     std::vector<std::wstring> string; /* optional element of XSD type xsd:string */  
  9.     struct soap *soap;  /* transient (not serialized) */  
  10. public:  
  11.     /// Return the unique type ID value SOAP_TYPE_WS1__ArrayOfString (12)  
  12.     virtual int soap_type(void) const { return 12; }  
  13.     /// Set object's data members to default values  
  14.     virtual void soap_default(struct soap*);  
  15.     /// Serialize object to prepare for SOAP 1.1/1.2 encoded output (or with SOAP_XML_GRAPH) by analyzing its (cyclic) structures  
  16.     virtual void soap_serialize(struct soap*) const;  
  17.     /// Output object in XML, compliant with SOAP 1.1 encoding style, return error code or SOAP_OK  
  18.     virtual int soap_put(struct soap*, const char *tag, const char *type) const;  
  19.     /// Output object in XML, with tag and optional id attribute and xsi:type, return error code or SOAP_OK  
  20.     virtual int soap_out(struct soap*, const char *tag, int id, const char *type) const;  
  21.     /// Get object from XML, compliant with SOAP 1.1 encoding style, return pointer to object or NULL on error  
  22.     virtual void *soap_get(struct soap*, const char *tag, const char *type);  
  23.     /// Get object from XML, with matching tag and type (NULL matches any tag and type), return pointer to object or NULL on error  
  24.     virtual void *soap_in(struct soap*, const char *tag, const char *type);  
  25.     /// Return a new object of type WS1__ArrayOfString, default initialized and not managed by a soap context  
  26.     virtual WS1__ArrayOfString *soap_alloc(void) const { return SOAP_NEW(WS1__ArrayOfString); }  
  27.              WS1__ArrayOfString() { WS1__ArrayOfString::soap_default(NULL); }  
  28.     virtual ~WS1__ArrayOfString() { }  
  29.     friend WS1__ArrayOfString *soap_instantiate_WS1__ArrayOfString(struct soap*, int, const char*, const char*, size_t*);  
  30. };  
  31. #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對象.

 

[cpp]  view plain  copy
 
  1.        _WS1__getWeatherbyCityName weatherName;  
  2. weatherName.soap = &proxy;  
  3. weatherName.theCityName = wszutf8;  
  4.   
  5. _WS1__getWeatherbyCityNameResponse weatherResponse;  
  6. proxy.getWeatherbyCityName(&weatherName, weatherResponse);  
  7.   
  8. for (int i = 0; i < weatherResponse.getWeatherbyCityNameResult->string.size(); i++)  
  9.     wcout << weatherResponse.getWeatherbyCityNameResult->string[i] << endl;  

原理與上面得到城市信息相同,就很少說了,下面貼出運行結果

 

 

我也是初次使用C++調用webService,若是有什麼更好的方法但願你們多交流

相關文章
相關標籤/搜索