C++请求web service与xml解析
1. C++解析XML的开源库
在项目中XML的解析使用的是开源的第三方库,TinyXML;这个解析库的模型通过XML文件,然后再内存中生成DOM模型,从而让我们能够非常方便的遍历这颗XML树。
DOM模型即文档对象模型,是将整个文档分成多个元素(如:书、章、节、段等),并利用树型结构表示这些元素之间的顺序关系以及嵌套包括关系。先看一下TinyXML中的主要类和XML文档之间的相应关系,下图是TinyXML中主要class的类图,反应各个类之间的静态关系。
TiXmlBase是全部类的基类,TiXmlNode、TiXmlAttribute两个类都继承自TiXMLBase类,当中TiXmlNode类指的是全部被<...>...<.../>包含的内容,而xml中的节点又详细分为下面几方面内容,各自是声明、凝视、节点以及节点间的文本,因此在TiXmlNode基础上又衍生出来这几个类TiXmlComment、TiXmlDeclaration、TiXmlDocument、TiXmlElement、TiXmlText、TiXmlUnknown,分别用来指明详细是xml中的哪一部分。TiXmlAttribute类不同于TiXmlNode,它指的是在尖括号中面的内容,像<...***=...>,当中***就是一个属性,这里採用一个XML文档详细说明一下:
1.<?xml version="1.0" encoding="UTF-8"?>
2.<phonebook>
3. <!--one item behalfs one contacted person.-->
4. <item>
5. <name>miaomaio</name>
6. <addr>Shaanxi Xi'an</addr>
7. <tel>13759911917</tel>
8. <email>miaomiao@home.com</email>
9. </item>
10. <item>
11. <name>gougou</name>
12. <addr>Liaoning Shenyang</addr>
13. <tel>15840330481</tel>
14. <email>gougou@home.com</email>
15. </item>
16. <!--more contacted persons.-->
</phonebook>
l 像TiXmlDeclaration指的就是<?xml version="1.0" encoding="UTF-8"?>,
l 像TiXmlComment指的就是<!--one item behalfs one contacted person.-->、<!--more contacted persons.-->,
l 像TiXmlDocument指的就是整个xml文档,
l 像TiXmlElement指的就是<phonebook>、<item>、<name>、<addr>等等这些节点,
l 像TiXmlText指的就是‘gougou’、‘15840330481’这些夹在<item>与</item>、<name>与</name>、<addr>与</addr>之间的文本文字,
l 像TiXmlAttribute指的就是<?xml version="1.0" encoding="UTF-8"?>节点中version、encoding,
l 除此之外就是TiXmlUnknown。
1) 读取XML文件
//!xml文件读取,模拟调用接口返回char *字符串
filebuf *pbuf;
ifstream filestr;
long size;
char *buffer; filestr.open(XML_EXAMPLE_FILE_NAME, ios::binary);
pbuf = filestr.rdbuf();
size = pbuf->pubseekoff(0,ios::end,ios::in);
pbuf->pubseekpos(0, ios::in); buffer = new char[size];
pbuf->sgetn(buffer, size);
filestr.close(); //!从xml字符串中获取相关值
string strCreationTime;
string strJobId;
string strJobType;
string strJobName;
string strJobLeader; TiXmlDocument *xmlDocument = new TiXmlDocument();
xmlDocument->Parse(buffer, 0, TIXML_DEFAULT_ENCODING); TiXmlElement *RootElement = xmlDocument->RootElement();
TiXmlElement *fileHeaderElement = RootElement->FirstChildElement();
TiXmlElement *fileBodyElement = fileHeaderElement->NextSiblingElement(); for (TiXmlElement *nodeElement = fileHeaderElement->FirstChildElement(); nodeElement; nodeElement = nodeElement->NextSiblingElement())
{
string strElementKey = nodeElement->Value();
if (strElementKey.compare(XML_PARSE_CREATION_TIME) == 0)
{
strCreationTime = nodeElement->GetText();
}
} for (TiXmlElement *nodeElement = fileBodyElement->FirstChildElement(); nodeElement; nodeElement = nodeElement->NextSiblingElement())
{
string strElementKey = nodeElement->Value();
if (strElementKey.compare(XML_PARSE_JOB_ID) == 0)
{
strJobId = nodeElement->GetText();
} if (strElementKey.compare(XML_PARSE_JOB_TYPE) == 0)
{
strJobType = nodeElement->GetText();
} if (strElementKey.compare(XML_PARSE_JOB_NAME) == 0)
{
strJobName = nodeElement->GetText();
} if (strElementKey.compare(XML_PARSE_JOB_LEADER) == 0)
{
strJobLeader = nodeElement->GetText();
}
}
2) 创建、生成XML文件
以例如以下XML文件为例:
<?xml version=”1.0” encoding=”gb2312”>
<InterFaceFile>
<FileHeader>
<MessageType>ProxyMiddleWareJobSearch</MessageType>
<Originator>WetLand</Originator>
<Recipient>Platform</Recipient>
<CreationTime>2014-9-18 10:25:20</CreationTime>
</FileHeader>
<FileBody>
<UserName>...</UserName>
<UserRoleID>13</UserRoleID>
<JobType></JobType>
</FileBody>
</InterFaceFile>
//! 构建XML字符串
TiXmlDocument *pDoc = new TiXmlDocument;
TiXmlDeclaration *pDeclaration = new TiXmlDeclaration("1.0", "gb2312", "");
pDoc->LinkEndChild(pDeclaration); TiXmlElement *pEleRoot = new TiXmlElement("InterFaceFile");
pDoc->LinkEndChild(pEleRoot); TiXmlElement *pEleFileHeader = new TiXmlElement("FileHeader");
TiXmlElement *pEleFileBody = new TiXmlElement("FileBody");
pEleRoot->LinkEndChild(pEleFileHeader);
pEleRoot->LinkEndChild(pEleFileBody); TiXmlElement *pEleMessageType = new TiXmlElement("MessageType");
TiXmlElement *pEleOriginator = new TiXmlElement("Originator");
TiXmlElement *pEleRecipient = new TiXmlElement("Recipient");
TiXmlElement *pEleCreationTime = new TiXmlElement("CreationTime");
pEleFileHeader->LinkEndChild(pEleMessageType);
pEleFileHeader->LinkEndChild(pEleOriginator);
pEleFileHeader->LinkEndChild(pEleRecipient);
pEleFileHeader->LinkEndChild(pEleCreationTime); TiXmlText *pEleMessageTypeText = new TiXmlText("ProxyMiddleWareJobSearch");
TiXmlText *pEleOriginatorText = new TiXmlText("WetLand");
TiXmlText *pEleRecipientText = new TiXmlText("Platform");
TiXmlText *pEleCreationTimeText = new TiXmlText("2014-9-18 10:25:20"); pEleMessageType->LinkEndChild(pEleMessageTypeText);
pEleOriginator->LinkEndChild(pEleOriginatorText);
pEleRecipient->LinkEndChild(pEleRecipientText);
pEleCreationTime->LinkEndChild(pEleCreationTimeText); //!
TiXmlElement *pEleUserName = new TiXmlElement("UserName");
TiXmlElement *pEleUserRoleID = new TiXmlElement("UserRoleID");
TiXmlElement *pEleJobType = new TiXmlElement("JobType");
pEleFileBody->LinkEndChild(pEleUserName);
pEleFileBody->LinkEndChild(pEleUserRoleID);
pEleFileBody->LinkEndChild(pEleJobType); TiXmlText *pEleUserNameText = new TiXmlText("...");
TiXmlText *pEleUserRoleIDText = new TiXmlText("13");
TiXmlText *pEleJobTypeText = new TiXmlText(""); pEleUserName->LinkEndChild(pEleUserNameText);
pEleUserRoleID->LinkEndChild(pEleUserRoleIDText);
pEleJobType->LinkEndChild(pEleJobTypeText); pDoc->SaveFile("E:/houqd.xml");
3) 生成XML字符串
生成XML字符串仅仅须要将如上的pDoc->SaveFile(“E:/houqd.xml”)替换为例如以下:
//!生成string字符串
TiXmlPrinter printer;
pDoc->Accept(&printer); string strRequest(printer.CStr());
2. C++调SOAP的开源库
我们採用gsoap作为开源的web service的实现框架,能够从网上下载到开源的代码实现。下载地址:http://gsoap2.sourceforge.net/ 一般下载的gsoap工具包中已经包括了生成Web Serviceclient须要用到的两个工具(可运行文件):wsdl2h.exe和soapcpp2.exe,windows开发包一般在gsoap/bin/win32下,默认情况下wsdl2h并不支持SSL,即无法訪问HTTPS网站,假设想要支持SSL等很多其它功能,就须要自己又一次配置编译该gsoap工具包,以生成新的wsdl2h.exe和soapcpp2.h。这里,我採用的是原生的文件。
相关參考资料:http://blog.csdn.net/zhaiwenjuan/article/details/6590941
1) gsoap生成本地代理
1> 依据wsdl生成对应的头文件
从Web服务提供者处获取Web Service的WSDL文件,一般是一个URL,如:http://www.somewebservice.com/Service?Wsdl,当然也能够是一个WSDL形式的XML文件。
使用gsoap的wsdl2h.exe,依据WSDL生成一个C/C++语法结构的头文件。
比如:wsdl2h.exe -s -o Service.h http://www.somewebservice.com/Service?Wsdl
这一步运行完后会得到一个头文件,如:Service.h
该步的目的:实现WSDL文件到.h文件的数据映射。
2> 依据生成的头文件生成相关代理文件
使用gsoap的预编译器soapcpp2.exe,依据上一步得到的头文件来生成存根文件soapStub.h和client代码框架:
如:soapcpp2.h -i -x -C -L Service.h
这一步将会得到几个.nsmap、.h和.cpp文件。该步的目的:生成对应的底层通信代码。
2) gsoap调用webservice接口
将上几步生成的文件增加到project中,并包括响应的头文件,并採用例如以下的调用方式:
string strRequest(printer.CStr()); //!web service调接口
string strWebServiceAddr = "http://172.16.10.209:8080/HDHT_J2EE/services/ProxyMiddleWareJob?wsdl";
ProxyMiddleWareJobHttpBindingProxy *proxy = new ProxyMiddleWareJobHttpBindingProxy(); _ns1__ProxyMiddleWareJobSearch inputParam;
_ns1__ProxyMiddleWareJobSearchResponse outputParam;
inputParam.in0 = const_cast<char *>(strRequest.c_str()); proxy->ProxyMiddleWareJobSearch(NULL,strWebServiceAddr.c_str() , &inputParam, outputParam); string strResult = outputParam.out;
3. 联调过程中出现的问题
1) 參数传递问题
这里,在使用web service调用接口时,依据曾经的思路(PHP的web service中的调用方式),想当然的将C++里面调用时參数的传递当成直接传递了,比如:上面调用ProxyMiddleWareJobSearch接口时,它接收一个xml格式的字符串,并返回一个xml格式的字符串,因此在刚開始使用时,採取的调用方式为:
Proxy->ProxyMiddleWareJobSearch(NULL, strWebServiceAddr.c_str(), strRequest, strResult);採用的字符串形式,结果一直报错,意思是无法将const char *转换为_ns1__ProxyMiddleWareJobSearch *的形式,在后来运用中发现应该例如以下使用:
_ns1__ProxyMiddleWareJobSearch inputParam; //! 代表输入
_ns1__ProxyMiddleWareJobSearchResponse outputParam; //!代表输出
inputParam.in0 = const_cast<char *>(strRequest.c_str()); //!输入第一个參数,
假设接口须要第二个參数,则调用方式为:inputParam.in1 = ...
string strResult = outputParam.out; //! 调用后结果的返回。
2) 中文乱码问题
解决方法:在Java构建web service端,返回字符串之前,先进行base64的加密,然后c++作为web service的client调用完方法后,先对字符串进行base64的解密,这样就不存在乱码问题了。
C++实现Base64的代码參考链接:
http://www.cnblogs.com/phinecos/archive/2008/10/10/1308272.html
C++请求web service与xml解析的更多相关文章
- 微软BI 之SSIS 系列 - 在 SSIS 中使用 Web Service 以及 XML 解析
开篇介绍 Web Service 的用途非常广几乎无处不在,像各大门户网站上的天气预报使用到的第三方 Web Service API,像手机客户端和服务器端的交互等都可以通过事先设计好的 Web Se ...
- 译-Web Service剖析: XML, SOAP 和WSDL 用于独立于平台的数据交换
本文是翻译内容,原文参见: Anatomy of a Web Service: XML, SOAP and WSDL for Platform-independent Data Exchange We ...
- iOS开发网络篇之Web Service和XML数据解析
郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主.捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下 ...
- web service json 数组解析
boolean workexpMark = true; // 美发师工作经历json数组解析 org.json.JSONObject jsonObject = new org.j ...
- C# 开发XML Web Service与Java开发WebService
一.web service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量 ...
- Web Service
Web Service全称XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量级的独立的通讯技术.是:通过SOAP ...
- 建立自己的Web service(SOAP篇)
1.简介 这篇文章主要介绍采用SOAP来建立以及访问Web service接口. Web service是一个平台独立的,低耦合的,自包含的.基于可编程的web的应用程序,可使用开放的XML(标准通用 ...
- 用.NET WebService Studio调试Web Service解决SOAPAction的问题
话说是这样的,这两天开发一个短信发送功能,客户给了一个 Web Service 地址(没有文档),让我调用就可以发送了, 我在VS 2013添加了服务引用,一切正常,可是执行代理方法时,怎么都报错 R ...
- Web Service(上)
1.XML CDATA指不应由XML解析器进行解析的文本数据. 在XML元素中,<和&是非法的.解析器会把字符<解释为新元素的开始,把字符&解释为字符实体的开始. 某些文本 ...
随机推荐
- Altium Designer中距离的测量
Ctrl+M 清除测量标签:点击右下角的清除按键
- Spring Boot 动态数据源(Spring 注解数据源)
本文实现案例场景:某系统除了需要从自己的主要数据库上读取和管理数据外,还有一部分业务涉及到其他多个数据库,要求可以在任何方法上可以灵活指定具体要操作的数据库. 为了在开发中以最简单的方法使用,本文基于 ...
- 《机器学习实战》---第二章 k近邻算法 kNN
下面的代码是在python3中运行, # -*- coding: utf-8 -*- """ Created on Tue Jul 3 17:29:27 2018 @au ...
- windows版 nginx配置反向代理实例教程 跳转tomcat和php网站
抄自 https://www.cnblogs.com/j-star/p/8785334.html 个人理解 nginx端口设置为80,简称n tomcat端口设置为其他,例如8080,简称t php网 ...
- 34、uevent机制说明
class_device_create(4.3.2内核是device_create->device_create_vargs->device_register->device_add ...
- [原]MFC中DIALOG(对话框)程序响应加速键(快捷键)
[原]MFC中DIALOG(对话框)程序响应加速键(快捷键) 2014-8-6阅读266 评论0 新建一个对话框程序,项目名为Test,删除默认确定,取消和静态文本框控件.添加一个按钮,Caption ...
- php面试题二--解决网站大流量高并发方案(从url到硬盘来解决高并发方案总结)
php面试题二--解决网站大流量高并发方案(从url到硬盘来解决高并发方案总结) 一.总结 从外到内解决网站大流量高并发问题---从提交一个url开始(从用户按下搜索栏回车键开始) url最开始会到d ...
- thinkphp3.2.3 excel导出,下载文件,包含图片
关于导出后出错的问题 https://segmentfault.com/q/1010000005330214 https://blog.csdn.net/ohmygirl/article/detail ...
- 阿里云服务器安全设置 分类: B3_LINUX 2014-07-24 11:10 5197人阅读 评论(1) 收藏
1.开启云盾所有服务 2.通过防火墙策略限制对外扫描行为 请您根据您的服务器操作系统,下载对应的脚本运行,运行后您的防火墙策略会封禁对外发包的行为,确保您的主机不会再出现恶意发包的情况,为您进行后续数 ...
- 菜单之二:使用xml文件定义菜单 分类: H1_ANDROID 2013-11-03 09:39 1038人阅读 评论(0) 收藏
参考<疯狂android讲义>2.10节 P174,参见归档project:XmlMenuDemo.zip 一般推荐使用XML文件定义菜单. 基本步骤如下: 1.定义布局文件 为简单显示原 ...