1. 程式人生 > >封裝tinyxml實現對UTF8和UNICODE編碼格式轉換

封裝tinyxml實現對UTF8和UNICODE編碼格式轉換

    tinyxml對儲存xml非常方便,但儲存的格式卻不是UTF8,導致實際使用中遇到讀取問題。

    為了方便使用,藉助對C++ 儲存檔案為UTF8編碼格式學習,實現對tinyxml的資料轉換做了一些封裝,使使用更加方便些。重點實現了UTF8_to_stringstring_to_UTF82個函式,然後在所有Get和Set函式中呼叫這2個函式,實現UTF8和UNICODE編碼格式轉換,細見一下程式碼: 

#pragma once

using namespace std;
#include <string>
#include <sstream>  
#include <COMUTIL.H>

#include "tinyxml.h"
#include "tinystr.h"

// 1. 實現各種資料型別轉換,特別是std::string 到 unicode CString 轉換 

struct CTinyXml
{
public:
	// 將字串轉成基礎資料型別,非基礎型別需顯示定義  
	template<class T>  
	bool StringToBaseType(const std::string& str, T& val)  
	{  
		std::istringstream stream;  
		stream.str(str);  
		if (stream >> val)  
		{  
			return true;  
		}  
		return false;  
	}  
	  
	// 將基礎資料型別轉成字串,非基礎型別需顯示定義  
	template<class T>  
	bool BaseTypeToString(const T& src, std::string& tar)  
	{  
		std::ostringstream stream;  
		if (stream << src)  
		{  
			tar = stream.str();  
			return true;  
		}  
		return false;  
	}  
	  
	template<class T>  
	static bool GetSubNodeValue(TiXmlElement *pElement, const std::string name, T& val)  
	{  
		if (!pElement) return false;  
		TiXmlElement *pTmpElement = pElement->FirstChildElement(name.c_str());  
		return GetNodeValue(pTmpElement, val);  
	}  

	template<class T>  
	static bool SetSubNodeValue(TiXmlElement *pElement, const std::string& name, T& val)  
	{  
		if (!pElement) return false;  
		TiXmlElement *pTmpElement = pElement->FirstChildElement(name.c_str());  
		return SetNodeValue(pTmpElement, val);  
	}  
public:
	static	int GetInt(string sText)
		{
			return _tstoi(GetText(sText));
		}
	static	int GetLong(string sText)
		{
			return _tstol(GetText(sText));
		}
	static	float GetFloat(string sText)
		{
			return float(_tstof(GetText(sText)));
		}
	static	double GetDouble(string sText)
		{
			return _tstof(GetText(sText));
		}

	static	CString GetText(string sText)
		{
			string sANS = UTF8_to_string(sText);

			CString strTxt;

			#ifdef _UNICODE
			{
				USES_CONVERSION;
				strTxt = A2W(sANS.c_str ());
			}
			#else
			{
				strTxt = sANS.c_str ();
			}
			#endif

			return strTxt;

		}
	static	string GetText(CString strText)
		{
			string sTxt;

			#ifdef _UNICODE
			{
				USES_CONVERSION;
				sTxt = W2A(strText);

			}
			#else
			{
				sTxt = strText;
			}
			#endif

			return sTxt;

		}

	static	_variant_t c_vt(const char*  pcVarType,const char*  pcVal)
		{
			_variant_t vtVal;
			string sVarType = pcVarType;
			string sVal = pcVal;

			if (sVarType == "VT_BOOL")	// 字串型別
			{
				vtVal.vt = VT_BOOL;

				if (sVal == "0")
					vtVal.boolVal = VARIANT_FALSE;
				else
					vtVal.boolVal = VARIANT_TRUE;

				return vtVal;
			}
			
			if (sVarType == "VT_I2")
			{
				vtVal.vt = VT_I2;
				vtVal.iVal = GetInt(sVal);
							
				return vtVal;
			}
			
			if (sVarType == "VT_I4")
			{
				vtVal.vt = VT_I4;
				vtVal.intVal = GetLong(sVal);

				return vtVal;
			}
			
			if (sVarType == "VT_R4")
			{
				vtVal.vt = VT_R4;
				vtVal.fltVal = GetFloat(sVal);

				return vtVal;
			}
			
			if (sVarType == "VT_R8")
			{
				vtVal.vt = VT_R8;
				vtVal.dblVal = GetDouble(sVal);

				return vtVal;
			}
			
			if (sVarType == "VT_BSTR")	// 字串型別
			{
				vtVal.vt = VT_BSTR;
				vtVal.SetString (sVal.c_str ());

				return vtVal;

			}

			return vtVal;
		}

	static	TiXmlElement* GetTiXmlElement(string sName,string sValue)
		{
			string sUtf8_Name = string_to_UTF8(sName);
			string sUtf8_Value = string_to_UTF8(sValue);

			TiXmlElement *pElement	= new TiXmlElement(sUtf8_Name.c_str());
	        TiXmlText *pXmlTxt = new TiXmlText(sUtf8_Value.c_str());

			if (pElement && pXmlTxt)
			{
				pElement->LinkEndChild(pXmlTxt);
				return pElement;
			}

			if (pElement)	delete pElement;
			if (pXmlTxt)	delete pXmlTxt;

			return NULL;
		}

	static	TiXmlElement* GetTiXmlElement(string sName,_variant_t vtValue)
		{
			CString strVal;
			CString strVT;
			switch(vtValue.vt)
			{
			case VT_I2:
				{
					strVal.Format (_T("%d"),vtValue.iVal);
					strVT = _T("VT_I2");
					break;
				}
			case VT_I4:
				{
					strVal.Format(_T("%d"),vtValue.intVal);
					strVT = _T("VT_I4");
					break;
				}
			case VT_R4:
				{
					strVal.Format(_T("%f"),vtValue.fltVal);
					strVT = _T("VT_R4");
					break;
				}
			case VT_R8:
				{
					strVal.Format(_T("%f"),vtValue.dblVal );
					strVT = _T("VT_R8");
					break;
				}
			case VT_BSTR:
				{
					strVal = vtValue.bstrVal;
					strVT = _T("VT_BSTR");
					break;
				}
			case VT_BOOL:
				{
					if (vtValue.boolVal == VARIANT_TRUE )
						strVal = _T("1");
					else 
						strVal = _T("0");

					strVT = _T("VT_BOOL");
					break;
				}
			default:
				return NULL;
				break;
			}

			string sVT = GetText(strVT);
			string sVal= GetText(strVal);

			TiXmlElement *pElement	= GetTiXmlElement(sName,sVal);
			pElement->SetAttribute ("VT",sVT.c_str ());

			return pElement;
		}
	static	TiXmlElement* GetTiXmlElement(string sName,double dValue)
		{
			CString strValue;
			strValue.Format(_T("%lf"),dValue);

			return GetTiXmlElement(sName,GetText(strValue));
		}
	static	TiXmlElement* GetTiXmlElement(string sName,int nValue)
		{
			CString strValue;
			strValue.Format(_T("%d"),nValue);

			return GetTiXmlElement(sName,GetText(strValue));
		}
	static	TiXmlElement* GetTiXmlElement(string sName,long nValue)
		{
			CString strValue;
			strValue.Format(_T("%ld"),nValue);

			return GetTiXmlElement(sName,GetText(strValue));
		}

	// ---->>-- 繫結元素
	static	TiXmlElement *	WriteElement(TiXmlElement *pParent,string sName)
		{
			string sVal;
			TiXmlElement* pElement = GetTiXmlElement(sName,sVal);
			pParent->LinkEndChild(pElement);

			return pElement;
		}
	static	TiXmlElement *	WriteElement(TiXmlElement *pParent,string sName, string sVal)
		{
			TiXmlElement* pElement = GetTiXmlElement(sName,sVal);
			pParent->LinkEndChild(pElement);

			return pElement;
		}
	static	TiXmlElement *	WriteElement(TiXmlElement *pParent,string sName,int& nVal)
		{
			TiXmlElement* pElement = GetTiXmlElement(sName,nVal);
			pParent->LinkEndChild(pElement);

			return pElement;
		}

	static	TiXmlElement *	WriteElement(TiXmlElement *pParent,string sName,UINT& unVal)
		{
			long lVal = (long) unVal;
			TiXmlElement* pElement = GetTiXmlElement(sName,lVal);
			pParent->LinkEndChild(pElement);

			return pElement;
		}

	static	TiXmlElement *	WriteElement(TiXmlElement *pParent,string sName,long& nVal)
		{
			TiXmlElement* pElement = GetTiXmlElement(sName,nVal);
			pParent->LinkEndChild(pElement);

			return pElement;
		}

	static	TiXmlElement *	WriteElement(TiXmlElement *pParent,string sName,ULONG& unVal)
		{
			long lVal = (long) unVal;
			TiXmlElement* pElement = GetTiXmlElement(sName,lVal);
			pParent->LinkEndChild(pElement);

			return pElement;
		}

	static	TiXmlElement *	WriteElement(TiXmlElement *pParent,string sName,float& fVal)
		{
			TiXmlElement* pElement = GetTiXmlElement(sName,(double)fVal);
			pParent->LinkEndChild(pElement);

			return pElement;
		}

	static	TiXmlElement *	WriteElement(TiXmlElement *pParent,string sName,double& dVal)
		{
			TiXmlElement* pElement = GetTiXmlElement(sName,dVal);
			pParent->LinkEndChild(pElement);

			return pElement;
		}

	static	TiXmlElement *	WriteElement(TiXmlElement *pParent,string sName,CString& strVal)
		{
			TiXmlElement* pElement = GetTiXmlElement(sName,GetText(strVal));
			pParent->LinkEndChild(pElement);

			return pElement;
		}
	// ----<<-- 繫結元素

public:
	//c++ string、UTF8相互轉換方法
	// 普通sting型別 轉UTF-8編碼格式字串
	static	std::string string_to_UTF8(const std::string & sANSI)
	{
		// 1. 轉成寬位元組的ANSI
		int nwLen = ::MultiByteToWideChar(CP_ACP, 0, sANSI.c_str(), -1, NULL, 0);

		wchar_t * pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然會出現尾巴
		::memset(pwBuf, 0, nwLen * 2 + 2);

		::MultiByteToWideChar(CP_ACP, 0, sANSI.c_str(), sANSI.length(), pwBuf, nwLen);

		int nLen = ::WideCharToMultiByte(CP_UTF8, 0, pwBuf, -1, NULL, NULL, NULL, NULL);

		char * pBuf = new char[nLen + 1];
		::memset(pBuf, 0, nLen + 1);

		// 2. 寬位元組的ANSI --> 多位元組的UTF8
		::WideCharToMultiByte(CP_UTF8, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);

		std::string sUTF8(pBuf);

		delete []pwBuf;
		delete []pBuf;

		pwBuf = NULL;
		pBuf = NULL;

		return sUTF8;
	}
	////////////////////////////////////////////////////////////////////////// 



	// UTF-8編碼格式字串  轉普通sting型別
	static	std::string UTF8_to_string(const std::string & sUTF8)
	{
		int nwLen = MultiByteToWideChar(CP_UTF8, 0, sUTF8.c_str(), -1, NULL, 0);

		wchar_t * pwBuf = new wchar_t[nwLen + 1];//一定要加1,不然會出現尾巴
		::memset(pwBuf, 0, nwLen * 2 + 2);

		::MultiByteToWideChar(CP_UTF8, 0, sUTF8.c_str(), sUTF8.length(), pwBuf, nwLen);

		int nLen = WideCharToMultiByte(CP_ACP, 0, pwBuf, -1, NULL, NULL, NULL, NULL);

		char * pBuf = new char[nLen + 1];
		::memset(pBuf, 0, nLen + 1);

		::WideCharToMultiByte(CP_ACP, 0, pwBuf, nwLen, pBuf, nLen, NULL, NULL);

		std::string sANSI = pBuf;

		delete []pBuf;
		delete []pwBuf;

		pBuf = NULL;
		pwBuf = NULL;

		return sANSI;
	}

};