27 五月, 2005
libxml2: how to bypass the UTF-8 checking of the parser when you use xmlReader
libxml2库功能很强大,除了早先的SAX和DOM解析方式外,在2.5.0版本以后,推出XmlTextReader接口,即保留了DOM的简便易用,又结合SAX的灵活高效,所以这次解析RSS,我选择的就是Reader方式。
实际使用中,碰到一个问题,libxml2内部的UTF-8合法性检察过于严格,只要碰到有不符合UTF-8编码的任何字符,它就会报错(Input is not proper UTF-8, indicate encoding !)并中止当前解析。当然,这种错误是由xml文档自身引起的,即便你使用传统的DOM或者SAX,都不能避免。
但是,rss文件中,这种小的编码错误还是比较常见的,象utblog的atom 0.3中有一项summary,截取文章的前200个字符,因为截取程序不判断文章编码,所以会出现半个UTF-8码的情形,这时候,libxml2解析程序就会执行失败。
那么,该如何跳过libxml2内部的UTF-8 checking呢?一个办法是直接修改libxml2源码,并重新编译。但是使用这个库的应用很多,仅仅为了这一个需求,就作这样的内部改动,扩展性和可用性都不强。仔细看了internalparser.c中相应的代码,在检查之前,程序会判断ctxt->charset == XML_CHAR_ENCODING_UTF8,如果有办法使得parser context(ctxt)的charset不等于XML_CHAR_ENCODING_UTF8,岂不是就可以了?
但是Reader接口没有公开_xmlTextReader结构的细节,所以为了能够得到ctxt,首先必须自己创建一个完全相同的structure。这个不难,直接从xmlreader.c中copy就是了,这样就取得了Reader的内部结构。
接下来,就是修改reader->ctxt->charset,我设置的值是ctxt->charset=XML_CHAR_ENCODING_ASCII + 99; 注意,这里不能设置为XML_CHAR_ENCODING_NONE,否则parser还是会重新设置此值。
测试下来,成功,原先解析失败的atom文档,现在可以顺利地被解析了。
不清楚bypass this internal UTF-8 checking可能会带来什么样的影响,只能到时候再说了。



