C++要求webサービスとxml解析

10576 ワード

1.C++解析XMLのオープンソースライブラリ
プロジェクトでのXMLの解析には、オープンソースのサードパーティライブラリ、TinyXMLが使用されます.この解析ライブラリのモデルはXMLファイルを介してメモリにDOMモデルを生成し、このXMLツリーを簡単に巡回することができます.
DOMモデルは、ドキュメント全体を複数の要素(本、章、節、セグメントなど)に分割し、ツリー構造を使用してこれらの要素間の順序関係およびネストされた包含関係を表すドキュメントオブジェクトモデルです.まず、TinyXMLの主要クラスとXMLドキュメントの対応関係を見てみましょう.次の図は、TinyXMLの主要classのクラス図で、各クラス間の静的関係を反映しています.
TiXmlBaseはすべてのクラスのベースクラスであり、TiXmlNode、TiXmlAttributeの2つのクラスはいずれも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のように,
lはTiXmlCommentのように,
lはTiXmlDocumentのようにxmlドキュメント全体を指します.
lはTiXmlElementのようになどのノードを指し、
l像TiXmlTextとは、の間に挟まれた「gougou」、「15840330481」というテキスト文字を指し、
lはTiXmlAttributeのようにノードの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サービスの実現フレームワークとして採用し、ネット上からオープンソースのコード実現にダウンロードすることができます.ダウンロードアドレス:http://gsoap2.sourceforge.net/一般的にダウンロードするgsoapツールパッケージには、Web Serviceclientを生成するために必要な2つのツール(実行可能ファイル):wsdl 2 hが含まれている.exeとsoapcpp 2.exe,windows開発パッケージは一般的にgsoap/bin/win 32の場合、デフォルトではwsdl 2 hはSSLをサポートしていない、すなわちHTTPSサイトにアクセスできない、SSLなど多くの他の機能をサポートするには、自分でもう一度gsoapツールパッケージを構成してコンパイルし、新しいwsdl 2 hを生成する必要がある.exeとsoapcpp 2.h.ここでは、オリジナルのファイルを採用しています.
関連参考資料:http://blog.csdn.net/zhaiwenjuan/article/details/6590941
1)gsoap生成ローカルエージェント
1>wsdlに基づいて対応するヘッダファイルを生成
WebサービスプロバイダからWebサービスのWSDLファイルを取得するには、次のようなURLが一般的です.http://www.somewebservice.com/Service?Wsdlあ、もちろんWSDL形式のXMLファイルであってもよい.
gsoapのwsdl 2 hを用いる.Exceは、WSDLに基づいてC/C++構文構造のヘッダファイルを生成します.
例えばwsdl 2 h.exe -s -o Service.h http://www.somewebservice.com/Service?Wsdl
このステップを実行すると、サービスなどのヘッダファイルが得られます.h
ステップの目的:WSDLファイルを実現する.hファイルのデータマッピング.
2>生成されたヘッダファイルから関連エージェントファイルを生成
gsoapのプリコンパイラsoapcpp 2を用いる.exeは、前のステップで得るヘッダファイルに基づいてルートファイルsoapStubを生成する.hとclientコードフレームワーク:
例:soapcpp 2.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)パラメータ伝達問題
ここで、ウェブサービス呼び出しインタフェースを使用する場合、従来の考え方(PHPのウェブサービスでの呼び出し方式)に従って、当然ながら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(strRequest.c_str()); //!最初のパラメータを入力し、
インタフェースに2番目のパラメータが必要であると仮定すると、呼び出し方式はinputParamである.in1 = ...
string strResult = outputParam.out;  //!呼び出し後の結果の戻り.
2)中国語の文字化けし問題
解決方法:Javaでwebサービス側を構築し、文字列を返す前にbase 64の暗号化を行い、c++でwebサービスのclientとしてメソッドを呼び出した後、文字列をbase 64の復号化を行い、文字列に乱符号化の問題がないようにする.
C++実装Base 64のコードリファレンスリンク:
http://www.cnblogs.com/phinecos/archive/2008/10/10/1308272.html