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>[email protected]</email>  
9.    </item>  
10.    <item>  
11.        <name>gougou</name>  
12.    <addr>Liaoning Shenyang</addr>  
13.    <tel>15840330481</tel>  
14.    <email>[email protected]</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 Service客户端需要用到的两个工具(可执行文件):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和客户端代码框架:

如:soapcpp2.h -i -x -C -L Service.h

这一步将会得到几个.nsmap、.h和.cpp文件。该步的目的:生成相应的底层通信代码。

2) gsoap调用webservice接口

将上几步生成的文件加入到工程中,并包含响应的头文件,并采用如下的调用方式:

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

时间: 2024-10-08 03:34:28

C++请求web service与xml解析的相关文章

iOS—请求Web Service

1.iOS SDK 同步GET请求 NSString *strURL = [[NSString alloc] initWithFormat:@"http://www.51work6.com/service/mynotes/[email protected]&type=JSON&action=query"]; strURL = [strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];

iOS开发网络篇之Web Service和XML数据解析

郝萌主倾心贡献,尊重作者的劳动成果,请勿转载. 假设文章对您有所帮助,欢迎给作者捐赠,支持郝萌主.捐赠数额任意,重在心意^_^ 我要捐赠: 点击捐赠 Cocos2d-X源代码下载:点我传送 游戏官方下载:http://dwz.cn/RwTjl 游戏视频预览:http://dwz.cn/RzHHd 游戏开发博客:http://dwz.cn/RzJzI 游戏源代码传送:http://dwz.cn/Nret1 在iPhone和后台系统的通信中,使用Web Service获取server数据上最常见的一

【Web基础】XML解析工具比较

DOM解析: 一次全部读入内存,随意存放修改,读取任何部分,次数无限制,异于开发,系统为开发者自动建立DOM树,XML对象模型由系统自动提供.缺点:需要一次读入内存,受文件大小限制,耗内存. SAX解析: 优点:顺序读入一部分进内存,不会一次加载,不受文件限制,由于部分读取.缺点:只能对文件按顺序读取解析,不能随机存取,不能修改,开发复杂,用户需自己定义时间处理.但开发比较灵活,可以用SAX建立自己的XML对象模型. JDOM:综合DOM解析和SAX解析的优点. DOM4J:强大,Hiberna

web service json 数组解析

?? boolean workexpMark = true; // 美发师工作经历json数组解析 org.json.JSONObject jsonObject = new org.json.JSONObject( workExperience); String array = jsonObject.getString("workExperence"); org.json.JSONArray jsonArray = new org.json.JSONArray(array); int

C#代码 请求web service soap类型服务(wsdl文件)

1.  首先搞到wsdl文件(客户提供的地址下载http://10.48.36.6:8080/ShuJuHuanJing.asmx?WSDL)网站中打开,复制到txt文件中存储为wsdlModel.wsdl.注意后缀. 2. 打开VS新建一个cs类用于存储转换wsdl文件 3. 在程序中打开VS中的命令行 4.  从wsdl路径下载至cs文件   输入命令:wsdl /language:c# /n:CHEER.PresentationLayer /out:文件存储路径 http://10.48.

iOS 中web service数据请求

Web Service也叫XML Web Service WebService是一种可以接收从Internet或者其它系统中传递过来的请求,轻量级的独立的通讯技术. #import <UIKit/UIKit.h> //遵循NSURLConnectionDataDelegate协议 @interface ViewController : UIViewController<NSURLConnectionDataDelegate> //接受从服务器返回的数据 @property(stro

关于 XML/EDI Web Service 小介绍

XML/EDI 系统的设计 总体框架 该 XML/EDI 系统分为四个层次: 第一层是提供 Web Service 的服务提供者,它包括服务提供者所能提供的所有服务(主要是与数据库之间的交互以及复杂功能的实现) 第二层是收集 Web Service 的服务代理,它主要收集所有的 Web Service 并对外发布,服务代理可以通过 Internet 或 Intranet 向服务中心发送远程调用信息,这些信息吧请求内容以 XML 数据格式表示且采用基于 HTTP 等通用 Internet 协议之上

MyEclipse 2013 Web Service 实现以xml格式数据传递

提示:由于版本问题,使用MyEclipse 2013web Service的框架只有JAX-WS和JAX-RS,就没有XFire这个框架了....个人觉得XFire不怎么好用 一,新建一个服务器端的Web Service Project项目 2,我的xml数据是从数据库中来的,所有在生成xml之前,要连接数据库查询出来放在集合里...这些过程码农们自己写咯.... 这个是查询出,生成xml格式数据的.... 3,最重要的发布service 4,现在就把你的项目发布到tomcat中,不过咧...肯

iOS 开发指南 第15章 访问Web Service之使用轻量级网络请求架构MKNetworkKIt

除苹果提供的NSURLConnection和NSURLRequest外第三方的网络框架 1 安装和配置MKNetworkKit框架 下载并打开MKNetworkKit目录添加MKNetworkKit文件夹到新工程中-添加支持的类库或框架 CFNetwork.framework SystemConfiguration.framework Security.framework-添加预编译头文件 #ifndef MyNotes/MyNotes-Prefix.pch #define MyNotes/My