天天看點

tinyxml的使用和字元編碼轉換

tinyxml定義的類或函數中涉及的字元大都是char,字元串指針也是char*或const char*,看一下面幾個函數:

const char* TiXmlElement::Attribute( const char* name ) const

int TiXmlElement::QueryIntAttribute( const char* name, int* ival ) const

...

這樣在你的應用程式中擷取的字元串就是const char*類型,如果你的XML文檔指定是UTF-8編碼(注意儲存的時候也是以UTF-8編碼方式儲存的),例如:

<?xml version="1.0" encoding="UTF-8">

<root>

<item>中文字元</item>

</root>

而你的應用程式可能是UNICODE,也可能是多位元組,那麼在應用程式中會這樣讀xml文檔:

TiXmlDocument doc("UTF8test.xml"); 

doc.LoadFile(TIXML_DEFAULT_ENCODING);//TIXML_DEFAULT_ENCODING指明按照UTF-8編碼方式讀取xml文檔

TiXmlElement* root = doc.RootElement();

TiXmlNode* node = root->FirstChild("item");

TiXmlElement* element = node->ToElement();

const char* text = element->GetText();

要注意此時的text,它指向的記憶體儲存的資料是一個char類型的字元,以0結尾,如果你将其直接輸出得到的将是亂碼,它的内容如下:

e4 b8 ad e6 96 87 e5 ad 97 e7 ac a6 00

這一串資料是儲存在檔案中的UTF-8編碼,它們是多位元組字元.

将其轉換為寬字元(寬字元的意思是:UNICODE 字元在記憶體中是以"UNICODE字元集中的序号"存在).

WCHAR wtext[MAX_PATH] = {0};

MultiByteToWideChar(CP_UTF8, 0, text, -1, wtext, MAX_PATH);

再看看wtext中的内容: 2d 4e 87 65 57 5b 26 7b 00 00

這是在記憶體中存放的UTF-8字元編碼的序号(UNICODE字元字元記憶體中存放的是其序号而不是其編碼).

再将wtext轉換為多字元(CP_ACP方式編碼) :

char sztext[MAX_PATH] = {0};

WideCharToMultiByte(CP_ACP, 0, wtext, -1, sztext, MAX_PATH, NULL, NULL);

再看看sztext中的内容: d6 d0 ce c4 d7 d6 b7 fb 00

可以看到,text,wtext,sztext指向記憶體中的資料并不相同.

還有一點,如果text中的内容是ASII嗎,你就不用轉換了,可以直接拿來使用.

在記憶體中動态生成XML檔案時,仍然是ANSI編碼方式,如下面代碼.

TiXmlDocument* m_pTinXMLDoc = new TiXmlDocument; 

TiXmlDeclaration* pdecl = new TiXmlDeclaration("1.0", "UTF-8", "yes"); 

m_pTinXMLDoc->LinkEndChild(pdecl); // <?xml version="1.0" encoding="UTF-8"?> 

// <TransmitInfo datetime="2012-10-10 19:10:23" cmd="1" category=""> 

TiXmlElement* pEleRoot = new TiXmlElement("RootNode"); 

pEleRoot->SetAttribute("id", "這是中文"); 

TiXmlElement* pNode = new TiXmlElement("中文标簽"); 

pNode->SetAttribute("中文屬性", "屬性值");

pEleRoot->LinkEndChild(pNode); 

m_pTinXMLDoc->LinkEndChild(pEleRoot); 

m_pTinXMLDoc->SaveFile("e:\\testansi.xml"); 

檔案内容如下:

<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>

<RootNode id="這是中文">

    <中文标簽 中文屬性="屬性值" />

</RootNode>

上面代碼需要注意一個調用:new TiXmlDeclaration("1.0", "UTF-8", "yes");參數"UTF-8"不是設定記憶體中xml檔案的編碼方式,而僅僅是這隻檔案頭encoding的屬性,跟檔案實際編碼方式無關.不過這樣做還是意義的,可以擷取檔案内容字元串,然後轉換為utf-8格式,在網絡上傳輸.如下代碼:

TiXmlPrinter printer; 

m_pTinXMLDoc->Accept(&printer); 

int nxmlBytes = printer.Size(); 

const char* xmlcstr = printer.CStr(); 

ASSERT(strlen(xmlcstr)==nxmlBytes && nxmlBytes<nLen); 

       //将xmlcstr轉換為utf-8 

       //...略. 

轉換之後,encoding=UTF-8真正表示檔案的編碼格式.

另外,調用SaveFile儲存到本地時,仍然是以ANSI字元格式儲存到本地.

是以,實際上xml檔案頭中的屬性encoding=UTF-8,但檔案未必是UTF-8編碼方式.

本文轉自jetyi51CTO部落格,原文連結: http://blog.51cto.com/jetyi/761708,如需轉載請自行聯系原作者