在Windows下使用TinyXML-2读取UTF-8编码包含中文字符的XML文件

时间:2023-01-06 14:33:41
        TinyXML-2 是一个用 C++ 开发的小巧、高效的 XML 解析工具,它在 GitHub 网站上的链接为:https://github.com/leethomason/tinyxml2 。它的结构非常精简,仅由 tinyxml2.h 和 tinyxml2.cpp 两个文件组成。TinyXML-2 能够处理 UTF-8 编码方式的 XML 文件,而 Windows 操作系统使用的文字编码方式是 UTF-16,所以如果在 Windows 平台上使用 TinyXML-2,应当留意编码方式的差异,有时需要进行编码转换。
        这里举一个简单例子:在简体中文版 Windows 7 平台上,要使用 TinyXML-2 处理一个包含中文字符、UTF-8 编码的 XML 文件,该文件名为 Example.xml,内容如下:

<?xml version="1.0" encoding="utf-8"?>
<material_list>
<circuit_board>电路板&amp;1号</circuit_board>
<supplier>http://amazon.com</supplier>
</material_list>

       现在要读取元素节点 circuit_board 中包含的文本节点(其实就是“电路板&1号”),示例程序如下:

/**************************************************   
* Author: HAN Wei
* Author's blog: http://blog.csdn.net/henter/
* Date: April 17th, 2017
* Description: demonstrate how to read XML content
including Chinese characters by using TinyXML-2
**************************************************/

#include "Windows.h"
#include "tinyxml2.h"
#include <iostream>
using namespace std;

int main(void)
{
char file_name[256] = {"Example.xml"};
wchar_t *buffer;
int buffer_len;
tinyxml2::XMLDocument doc;
tinyxml2::XMLText* CircuitBoardTextNode;

_wsetlocale(LC_ALL, L"chs");
doc.LoadFile(file_name);
if ( doc.ErrorID() )
{
wprintf(L"加载配置文件出错!\n");
system("pause");
return (-1);
}
doc.Print();
CircuitBoardTextNode = doc.FirstChildElement("material_list")->FirstChildElement("circuit_board")->FirstChild()->ToText();
const char* CircuitBoardName = CircuitBoardTextNode->Value();

if ( !(buffer_len = MultiByteToWideChar(CP_UTF8, 0, CircuitBoardName, -1, NULL, 0)) )
{
wprintf(L"编码转换错误!\n");
system("pause");
return (-1);
}
buffer = new wchar_t[buffer_len];
if ( !(MultiByteToWideChar(CP_UTF8, 0, CircuitBoardName, -1, buffer, buffer_len)) )
{
wprintf(L"编码转换错误!\n");
system("pause");
return (-1);
}

wprintf(L"\n%ls\n\n", buffer);
delete [] buffer;
system("pause");
return 0;
}

        使用Visual Studio编译并执行这个程序,输出结果如下:

在Windows下使用TinyXML-2读取UTF-8编码包含中文字符的XML文件

         从输出结果可以看出:
1. 使用 TinyXML-2 从 XML 中读取内容时,会将读出的字符串以 char 数组形式存储。在中文版 Windows 操作系统中,使用 tinyxml2::XMLDocument 类的 Print( ) 方法输出 XML 文件的内容时,如果输出内容是可显示的 ASCII 字符,不会有任何问题;如果输出内容是 UTF-8 编码的中文字符,则会显示乱码。

2. 为了能在 Windows 中正确显示 XML 中包含的中文字符,可以使用 Kernel32.dll 中包含的 MultiByteToWideChar( ) 函数,将 UTF-8 编码的中文字符转换为 UTF-16 编码方式的中文字符。在 Windows 中能正确显示 UTF-16 编码的中文字符,不会出现乱码。

3. 使用 tinyxml2::XMLDocument 类的 Print( ) 方法输出 XML 文件中的内容时,Print( ) 方法不会对 XML 规范中定义的转义字符做转换。在本例中,Print( ) 方法被调用后,并未将 &amp; 转换为 & 。

4. 当 tinyxml2::XMLNode::ToText( ) 方法被调用时,会自动处理 XML 规范中定义的转义字符。在本例中,将 &amp; 自动转换为 & ,不需要编程者再做处理。

        在文本编辑器 EditPlus 或 Notepad++ 中,能够选择文件编码方式,操作类似于下图:

在Windows下使用TinyXML-2读取UTF-8编码包含中文字符的XML文件

        对于 Example.xml 这个文件,不管以包含 BOM 的 UTF-8 编码方式保存它,还是以不带 BOM 的 UTF-8 编码方式保存它,运行上面的示例程序,发现都能够正常执行。由此可知,对于 UTF-8 编码的 XML 文件中包含或不包含 BOM 这两种情况,TinyXML-2 都能够正确处理。