转载: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] = {};
MultiByteToWideChar(CP_UTF8, , text, -, wtext, MAX_PATH);
再看看wtext中的内容: 2d 4e 87 65 57 5b 26 7b 00 00
这是在内存中存放的UTF-8字符编码的序号(UNICODE字符字符内存中存放的是其序号而不是其编码).
 
再将wtext转换为多字符(CP_ACP方式编码) :
char sztext[MAX_PATH] = {};
WideCharToMultiByte(CP_ACP, , wtext, -, 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编码方式

C++ tinyXML的使用和字符编码转换的更多相关文章

  1. iconv字符编码转换

    转自 http://blog.csdn.net/langresser_king/article/details/7459367 iconv(http://www.gnu.org/software/li ...

  2. Char Tools,方便的字符编码转换小工具

    工作关系,常有字符编码转换方面的需要,写了这个小工具 Char Tools是一款方便的字符编码转换小工具,基于.Net Framework 2.0 Winform开发 主要功能 URL编码:URLEn ...

  3. php 字符编码转换函数 iconv mb_convert_encoding比较

    在使用PHP处理字符串时,我们经常会碰到字符编码转换的问题,你碰到过iconv转换失败吗? 发现问题时,网上搜了搜,才发现iconv原来有bug ,碰到一些生僻字就会无法转换,当然了配置第二个参数时, ...

  4. 编码问题 php字符编码转换类

    各种平台和软件打开显示的编码问题,需要使用不同的编码,根据我们不同的需求. php 字符编码转换类,支持ANSI.Unicode.Unicode big endian.UTF-8.UTF-8+Bom ...

  5. Python—字符编码转换、函数基本操作

    字符编码转换 函数 #声明文件编码,格式如下: #-*- coding:utf-8 -*- 注意此处只是声明了文件编码格式,python的默认编码还是unicode 字符编码转换: import sy ...

  6. php字符编码转换之gb2312转为utf8(转)

    在php中字符编码转换我们一般会用到iconv与mb_convert_encoding进行操作,但是mb_convert_encoding在转换性能上比iconv要差很多哦.string iconv ...

  7. day4学python 字符编码转换+元组概念

    字符编码转换+元组概念 字符编码转换 #coding:gbk //此处必声明 文件编码(看右下角编码格式) #用来得到python默认编码 import sys print(sys.getdefaul ...

  8. erlang中字符编码转换(转)

    转自:http://www.thinksaas.cn/group/topic/244329/ 功能说明: erlang中对各种语言的编码支持不足,此代码是使用erlang驱动了著名的iconv编码库来 ...

  9. Qt代码区字符编码转换

    在做通讯练习的时候,发现发送给小助手字符乱码,图片如下 本人Qt Creator是UTF-8,需要改成gbk,代码如下 #include<QTextCodec> // 提供字符编码转换 Q ...

随机推荐

  1. Ubuntu 16.04配置国内高速apt-get更新源

    https://www.linuxidc.com/Linux/2017-11/148627.htm Ubuntu 16.04下载软件速度有点慢,因为默认的是从国外下载软件,那就更换到国内比较好的快速更 ...

  2. Django自带的登录功能

    https://www.cnblogs.com/wspblog/p/6634262.html

  3. 带宽bandwidth,也叫频宽

    1.两种意义 (1)在数字设备中,带宽通常以bps(bit per second)或bit/s或b/s表示. (2)在模拟设备中,带宽通常以每秒传送周期或赫兹 (Hz)来表示.如传送模拟信号(连续变化 ...

  4. iframs刷新的两种方法

    <iframe src="a1.html" id="iframe1Id" name="iframe1Name" width=" ...

  5. 远程开关机神器Wake On LAN,免费有中文版

    https://wol.aquilatech.com/ Wake On Lan 又名 aquilaWOL,这是一款免费且开源的图形界面 WOL 软件,有繁体中文界面,可以管理多台电脑和网络设备,支持批 ...

  6. spring 装配集合

    1:创建pojo,属性包含集合,集合元素为基本类型 package com.liyafei.pojo; import java.util.List; import java.util.Map; imp ...

  7. (转)Elasticsearch聚合初探——metric篇

    前言 ES中的聚合被分为两大类:Metric度量和bucket桶(原谅我英语差,找不到合适的词语.....就用单词来说吧!).说的通俗点,metric很像SQL中的avg.max.min等方法,而bu ...

  8. UUID生成字符串

    在向数据库插入新数据时,可能需要插入字符串形式的ID,这时使用UUID可以生成随机字符串: String str = UUID.randomUUID().toString();

  9. CentOS系统下的数据盘挂载

    此教程适用系统:Linux(CentOS,Debian,Ubuntu,Fedora) 通常新开通的Linux云服务器数据盘都未做分区和格式化.在进行数据盘挂载之前我们要先进行分区以及格式化操作.注意, ...

  10. entity framework 新增,更新,事务

    protected void Button1_Click(object sender, EventArgs e) { yyEntities _db; _db = new yyEntities(); t ...