老星头的JoJo技术花园

主要花草:XML 园间杂草:SNMP C++ JAVA :)
posts - 4, comments - 11, trackbacks - 0, articles - 0

上周为项目做了一个小工具,需要由一颗内存树生成XML文档。
由于是在WIN平台,C++环境下编程,所以我选择了APACHE项目下
的XERCES-C作为软件平台进行开发。

XERCES-C是一款优秀的XML开发包。对DOM,SAX等技术做了比较完美
的实现。相关的信息请查看
http:\\xml.apache.org\xerces-c

但是在开发中,遇到了一个不大不小的问题,就是将内存中的DOM树导出
到文件的时候,默认生成的XML文档的encoding属性是UTF-16编码的,
但是内容却是UTF-8编码的,这样的XML文档实际上是无法被程序处理的。
更郁闷的是,无论我如何设置DOMDocument ,DOMWriter的Encoding 属性,
输出的东西永远都是这个样子的。输入中文那更是想都别想了。

那么如何把XML文档的编码设置成GB2312呢?
我BAIDU,GOOGLE了半天,发现因为这个问题所困扰的兄弟还真不少,
而且也没有太有效的解决办法,甚至有一个哥们无奈之下,干脆自己写了
一个XML解析器(汗。。。)。

经过这几天的工作,我发现了一些这个问题的解决之道,愿与大家分享。

1。 对于文档对象DOMDocument ,在代码中一般是一个名为doc的指针,
它的方法setEncoding ,setAcutalEncoding 对于最后生成的XML代码的编码
好像是没有影响的,但是保险起见,先把他们都设置为
doc->setEncoding(XMLString::transcode("GB2312"));
doc->setAcutalEncoding(XMLString::transcode("GB2312"));
注意,最好是你在对DOM树操作前进行设置。

2。也是最重要的一点,我在网上看到大家一般是用
DOMWriter 的 writeToString 将内存中的DOM树写入文件的,
但是经过我试验,应该用 writeNode 方法将DOM树写入文件。
具体代码如下:

DOMWriter* writer = impl->createDOMWriter(); //其中的impl是文档对象实例
writer->setEncoding(XMLString::transcode("GB2312")); //注意,这和上面讲的doc不是同一个对象

XMLFormatTarget *mytarget;
mytarget = new LocalFileFormatTarget(".\example.xml"); // 这一行创建一个XMLTarget,指向你要写入的文件路径

writer->writeNode(mytarget,*doc);// doc是你的文档对象
writer->release();

用以上代码的方式生成的XML文档就是GB2312编码的了,
以后在文档中增删改查中文都没有问题了。

后记:
核心的问题实际上是不能用writeToString写入文件,改用
writeNode就可以了。由于writeToString实际上是返回了一个
char* ,然后我们又要用一些其他方式,比如fprintf等等方式,
将这个字符串写入文件,我怀疑是在这一步中,出了问题,
我们调用的写文件函数将其自动转码了。但是我将内存中
的这个char*直接输出到屏幕上的时候,居然也是UTF-16的,
估计真的是 writeToString 这个函数有问题吧。

基于XERCES-C编程的人本来就少,大部分人都是基于XERCES-J
在工作。所以XERCES-C相关的使用经验等东西网上就很少,
希望这篇文章可以帮助有需要的兄弟,同时也希望大家都把自己
的使用经验POST一下,共同进步:)

(PS:四个月更新一次blog,我彻底输给我自己了,T.T,以后再忙也要坚持更新)



 

Feedback

# re: 基于XERCES-C编程中的中文(encoding)设置问题的解决方法  回复  更多评论   

2006-07-14 16:42 by Learning
我也刚刚接触xerces-c的开发。但遇到好多问题:(下了包后需要配置吗?里面的include和lib文件怎么处理?希望详细介绍下步骤,最好配上简单的实现代码。
正如你所说,网上资料太少了,先谢过!

# re: 基于XERCES-C编程中的中文(encoding)设置问题的解决方法  回复  更多评论   

2007-05-12 21:15 by realone
大哥,你的方法的确可以实现,很有参考价值.
不过用writeNode有个问题啊,就是写进去的文件,如果你在同一个程序里马上就去读取的话,读不到任何内容啊.这个问题大哥知道如何解决吗?

# re: 基于XERCES-C编程中的中文(encoding)设置问题的解决方法  回复  更多评论   

2007-05-13 21:25 by 小乔的老哥
XERCES 是独占写的,你必须把writer关闭以后,才可以读取。其实你要明白XERCES在把XML导入为DOMDocument后,就是独立的一份了,这个时候你把源XML删除了都没关系,你也可以把这个DOMDocument写到任何地方,所以不用读作为缓存写进行的那个文件,其他人也要读的话,直接把DOMDocument*指针给他们,让他们直接操作就OK了。你用addNode之类的方法对DOMDocument树做的任何改动,都是立即在内存中生效的,不是写回到文件才生效。(主观臆断了您的需求,不知道有没有猜对呵呵,如果不是,请再联系呵呵 :)

# re: 基于XERCES-C编程中的中文(encoding)设置问题的解决方法  回复  更多评论   

2007-05-13 22:52 by realone
谢谢大哥,你说的很对.(没有臆断啦 :) ).可是我要用SOCKET发送这个XML该怎么做呢?是直接用DOMDocument*吗?都不知道唉.小弟是个初学者啦.再次感谢大哥的回复,由衷的致谢!

# re: 基于XERCES-C编程中的中文(encoding)设置问题的解决方法  回复  更多评论   

2007-05-14 21:40 by 小乔的老哥
....原来是有这样的需求啊,那的确没什么太好的办法了,缓存到文件可能是较常用的方法了。建议你写到一个临时文件中,然后关闭writer,然后用文件I/O 的API读出文件内容,发到SOCKET上。 :)

# re: 基于XERCES-C编程中的中文(encoding)设置问题的解决方法  回复  更多评论   

2014-09-11 15:27 by godfather
请教下,读取分析文件使用parse文件,但是文件是一个乱码(或者说不是XML方式文件),如何避免软件死?我用的是xerces 3.1.1
只有注册用户登录后才能发表评论。