Xerces-C 2.10]GB2312支持的问题

Xerces-C 2.1.0 本身是不支持GB2312编码的,就是说你不能直接
用它去操作GB2312编码的xml文件,需要打patch。
  
问题是出在Win32TransService、Win32LCPTranscoder、Win32Transcoder
上(别的平台是其相应的Transxxxxxx)
  
我只说说Win32平台的修改办法,其他平台如果有问题,你需要自己
去跟踪解决。
  
下面是Xerces的程序流程:
  
首先,Xerces做parse前第一步是将xml文件从原来的编码转换成UTF-16。
而在Win32下的代码转换工作( XML文件的原始编码<-> UTF-16 ) 是由
Win32TransService、Win32LCPTranscoder、Win32Transcoder完成,都在
Win32TransService.hpp中定义。
  
其中LCPTranscoder是为XMLString::transcode服务的,而在将xml文件
内容转换成为UTF-16中用的是Win32TransService,TransService会去new
一个Win32Transcoder。XMLRecognizer会去比较XML文件的前若干字节,
试图判断出文件的编码是ASCII/UTF-16LE/UTF-16BE/UTF-32中的那一种。
这个很大程度上是靠BOM和前面的<?xml这几个字符来判断的。
对于GB2312编码的xml文件来说,Xerces都应该会识别为ASCII(MBCS?),
因为GB2312没有BOM,前面的"<?xml"和普通的ASCII也一样(这个我是一
半跟踪,一半靠猜的)。
  
然后xerces会去查找"encoding=LANG"这个声明。如果没有encoding声明,
比如:
         <?xml version="1.0" ?>  
         <AB>一二三四五六七八九12345678</AB>
  
parse的时候就会出错,自己用Xerces的例子DOMPrint试试就知道了。
但如果上面的例子加入了"encoding=GB2312",那么xerces就可以知道这是
什么多字节编码,然后用注册表的API去HCR\MIME\Database\Charset中查找
encoding后面那个字符串的Section(即"GB2312"),从而得到GB2312对应的
Codepage(936)。有了codepage代号,在Win32Transcoder里面的就可以调用
WideCharToMultiByte和MultiByteToWideChar两个API函数进行
GB2312<->UTF-16(Unicode)之间转换,而其中最重要的参数codepage就是上
面提到的那个文件编码对应的代码页(对GB2312就是936)。
至此,xml文档由原来编码转换成UTF-16就可以顺利完成了。其核心是将编码
命名(GB2312)对应的codepage代号936找到,然后调用Windows API实现
GB2312<->UTF-16。
  
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
(以上部分是以前写的,应该都是准确的,下面的是现在写的,因为现在很久
没玩了Xerces-C++了,所以靠的是回忆。不一定准确,如果有出入,请自行解决)
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  
只要你的Win32上装了cp936,这个转换都是会成功的。就是说,Xerces-C++
能正确读入和解析GB2312的文件。但是当你用XMLString::transcode会友问题。
上面说过,XMLString用的是LCPTranscoder。而Win32LCPTranscoder有问题。
它用wcstombs和mbstowcs去做Local codepage <-> Unicode,但是却没有首先
setlocale,所以wcstombs,mbstowcs根本根本不知道local codepage是什么。
所以,加入以下一行
  
Win32LCPTranscoder::Win32LCPTranscoder()
{
#ifdef XERCES_DEBUG
         cout << "Setlocale(LC_CTYPE):" << setlocale(LC_CTYPE,"") << "\n" << endl;
#else
         setlocale(LC_CTYPE,"");  //选用系统default codepage
#endif
}
  
上面代码是在Win2k CHS版本中的,因为简体中文版的default codepage就是cp936,
即GBK。如果你是Win2K Englist版本,想用中文,应该
    setlocale(LC_CTYPE, ".cp936");
  
  
下面是一个以前写的XMLString测试程序,你可以在在patch前后运行一下,看看
XMLString的效果。
  
  
test.cpp
------------------------------------
int main(int argc,char* argv[])
{
     //Sets the locale to the default, which is the system-default                                   //code page obtained from the operating system.  
     setlocale(LC_CTYPE,"");  
          
     // Initialize the XML4C2 system
     try
     {
          XMLPlatformUtils::Initialize();
     }
     catch (const XMLException& toCatch)
     {
          cerr << "Error during initialization! :\n"
               << StrX(toCatch.getMessage()) << endl;
          return 1;
     }
      
     //a Chinese Character in MBCS, 2 bytes(0xB5,0xE7).
     // in Unicode, it should be 0x7535(2 bytes)
     char szTEST[] = "电";    
     //so:  szTEST[0]:0xB5, szTEST[1]:0xE7, szTEST[2]:0x00, strlen(szTEST) = 2;
     assert(strlen(szTEST)== 2);
  
     XMLCh* xTEST = XMLString::transcode(szTEST);
      
     //the character is 0x7535 in unicode, wcslen(xTEST)=1
     assert(xTEST[0] == 0x7535 && xTEST[1] == 0);    //error in here
      
     //actual result:xTEST[0]:0x00B5 , xTEST[1]:0x00E7 , xTEST[2]: 0x0000 ,
     //wcslen(xTEST) = 2
      
     //but, the functions: mbstowcs & wcstombs is correct
     wchar_t wcs[2] = L"";
  
     return 0;
}
  
在main()第一行,我加入了setlocale(),但是如果LCPTranscoder中的mbstowcs依然不能
正常工作,必须patch.但是main()中直接调mbstowcs是正常的。
  
  
写得有点乱,因为最近忙,而且很久没用Xerces-C++,好多东西忘了。有问题自己去跟踪
吧。
  
  
各平台下测试Xerces-C对特定编码的支持,可按照以下步骤:
  
先测试XMLString是否正确支持 Local codepage <-> UTF-16,如果OK,
说明LCPTranscoder没有问题。
  
然后测试Xerces-C++能否正确读入指定编码的xml文件,如果OK就说明Transcoder没有
问题。自己去给有问题的地方打patch。
  
LCPTranscoder的问题一半出在mbstowcs,wcstombs,往往是locale不对。
Transcoder的问题出在系统没有提供 xml文件编码<->UTF-16 的库,或者查找/调用这个
库的时候有问题。
  
Win32平台的问题就是出在LCPTranscoder
而Linux平台下是因为Transcoder和LCPTranscoder都有问题。
  
需要注意的是,Linux的wchar_t是32位的UTF32,如果要转换成UTF16,有两个方法:
1) 用iconv库,直接从 xml文件编码<->UTF16, IconvGNU TransService用的就是这个
2) 用mbstowbc和wcstombs
  
                  mbstowcs            位操作
    xml文件编码 <---------> UTF-32 <----------> UTF-16
                  wcstombs            位操作  
  
  
  
"AS-IS" article
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值