RAPDIDxml作为一种高效的XML解析库被很多人推荐和使用,但在很多使用举例中,都是使用UTF-8编码的字符串处理。在库的帮助手册中也说对UTF-16支持不好。
我在做测试时发现工程使用UNICODE编码,字符串使用WSTRING,甚至XML内容中包含中文字符,简单测试时均可以正常解析,那为什么说对UTF-16支持不好?看源码,确实内部处理基本上都是使用模版CH,根据传入的类型是CHAR或者WCHAR自动区分。难道是新的库已经解决这些问题了?
高兴了没多久,准备进一步实际测试RAPIDxml的性能和TINYxml的性能对比时,使用了一个本地比较大的表,有几百条数据,多个字段,字段内容有英文中文,测试时发现TINYxml解析正常,RAPIDxml解析老是出现异常,开始以为是自己对字符串内存使用不正确(这个是RAPIDxml使用需要注意的地方),后面各种调整(使用数组--太大不行;使用文件-读入出问题;使用向量;向末尾自己加结束符号......),后来使用RAPIDxml自己的分配字符串重新申请保存还是不行,感觉不对,明明单独测试中文可以支持为什么这样不行?
后来把表内容查询从整表查询变为1条查询发现解析OK,怀疑表中有内容在解析时出错(特殊的字符解析出错),经过按照ID排除,发现有一条记录解析肯定出错,把记录内容16禁止打印发现,有个中文字符UTF-16编码为0x5f00,和其它不太一样(其它多为0x00yy或者0xyyyy),RAPIDxml解析时会去判断字符串结束符号,这个0x5f00会不会被误以为字符串结束,导致后面解析异常。
单独把0x5f00对应的中文字符“开”测试解析,每次必然异常。跟踪调试发现,在RAPIDxml解析过程中会对XML中的关键字符,如<、>、空格等进行匹配分析,匹配分析时是和一个unsigned char类型的数组进行比较的,0x5f00必然会出现异常。
具体原因为:xml底层解析查找一些关键字(空格、结束符号、>、<等)时,是和一个静态定义的unsigned char类型数组(256大小)进行匹配的,如果输入字符为wchar类型,则强制转换后比较,这样,对于utf16类型由于裁剪了后面部分,可能一个汉字会被当作一个char字符处理,特别是后面一个字节为00的会当作结束符处理(0x6253 0x5f00 0x6743 0x9650),后面字节如果和ascii码相同也可能被误处理。
搞清楚原因,解决起来也很容易:汉字肯定是内容,不会是关键字,不用做特殊处理&