转载:http://jetyi.blog.51cto.com/1460128/761708/
关于tinyxml使用的文档有很多(这篇文章就写的很好),这里仅提一下字符编码的转换问题,如果你不熟悉字符编码最好先阅读一下计算机内存和文件中的UNICODE字符.
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编码方式