libxml2中处理中文
在上篇中简单介绍了libxml2读写XML文件。
本篇将介绍如何在libxml2中读写中文数据。
libxml2中提供了编解码器,通过建立自己的编码接口由libxml根据当前编码进行调用,实质上是使用iconv库中的函数实现转换。一般情况下XML使用UTF-8编码,可以实现很好的跨平台性。
本文将网络上的一段代码复制下来,并应用于系统中,并在32位与64位LINUX平台下测试通过。(源于网络的在64下有问题,我调试了2个多小时才找到问题所在)既然思想来源于网络,在这里也将代码公布在这里。这样就可以直接应用于代码中。
使用上述代码的方式就是将编码转换初始化,并插入到XML库的接口中。
就是使用iconv库(LINUX中存在的,libxml也是使用该库),建立utf-8编码与gbk编码的转换接口,并将接口插入到libxml2库中,这样xml库就支持对gb2312和gbk编码的支持了。当然,这个转换不会自动完成,我们需要使用从libxml库中查找特定编码的接口,libxml支持一些基本的编码接口,如:ISO-8859-1,ISO-8859-2等编码,但不支持gbk,所以在上述代码中,我们定义了gbk_input,与gbk_output两个接口,这两个接口是libxml库的标准声明。
Function type: xmlCharEncodingInputFunc
Function type: xmlCharEncodingInputFunc int xmlCharEncodingInputFunc (unsigned char * out,
int * outlen,
const unsigned char * in,
int * inlen)
Take a block of chars in the original encoding and try to convert it to an UTF-8 block of chars out.
out: | a pointer to an array of bytes to store the UTF-8 result |
outlen: | the length of @out |
in: | a pointer to an array of chars in the original encoding |
inlen: | the length of @in |
Returns: | the number of bytes written, -1 if lack of space, or -2 if the transcoding failed. The value of @inlen after return is the number of octets consumed if the return value is positive, else unpredictiable. The value of @outlen after return is the number of octets consumed. |
还有一个xmlCharEncodingOutputFunc函数,声明与上面是一样的。
在ConvertInput与ConvertFrom是在libxml库中查找指定编码的接口,并完成编码转换。为了支持GBK,通过xmlNewCharEncodingHandler 来添加新的编码到该编码器中,ConvertXXXX从编码库中找到相应编码的处理器,完成编码与解码工作。
在实际使用的时候就是使用ConvertXXXX来实现编码与解码。
如:
这两个函数返回的是一个字符串指针,内存由ConvertXXX函数分配,需要使用free函数释放。
在使用完libxml库之后,我们需要释放由iconv_open打开的转换句柄,并且还要释放libxml库的转换资源。
xmlCleanupCharEncodingHandlers();
用上述来释放libxml库中的资源。
后记:
使用网上的代码,是非常快速的编码方式,当然,我也直接使用了网上的代码,但移植到64位平台时出现了问题,导致浪费了不少的调试时间(使用gdb在代码中查看,使用printf打印指针值,数据....痛苦!)。在上面的代码中,我加入了警示注释,希望自己记住,下次看到这样的代码就知道有问题。
指针之间的转换编码器是不会告警,所以也没有多注意,那个一整形指针转换成size_t指针类型时,问题在不同平台就会产生问题。size_t定义为平台的数据长度,而int在依然是32位(不保证不变)。
int a = 10;
int *pa = &a;
size_t b;
size_t *pb;
pb = pa;
b = *pb;
printf("a:%d, b:%zd/n", a, b);
如上一段简单的代码,在32位平台上输出都是10,64位平台之上输出为a:10, b:-1306831365601230838
后面那个值是不定的,如果使用-Wall 编码选项,gcc会报一个警告在pb = pa;如果你在32位平台使用pb = (size_t*)pb;那编码器就不会报警,而网上的一份代码就是这样。这也不能责怪源作者,可以环境的不同,考虑自然也就不多了。
所以,当指针类型转换的时候,一定要注意这个类型,你是否很了解。长度是不是一样的?否则问题出现在平台问题上,是很常难以找到问题所在的。
版权声明:本文为博主原创文章,未经博主允许不得转载。