内置XmlPullParser的替代方案,具有良好的编码支持

时间:2013-05-09 16:38:41

标签: java android xml xmlpullparser

我正在将为BlackBerry(Java)编写的项目移植到Android。该项目包含一些针对org.xmlpull.v1.XmlPullParser接口编写的xml解析类。实际的解析器实例从外部注入这些类。

此应用程序解析以ISO-8859-15(又名拉丁语9)编码的xml文件。我不能使用UTF-8,不幸的是我需要坚持这种编码。

旧的BlackBerry项目使用了kxml2拉解析器。现在在android中我试图使用可以像这样获得的内置解析器:

XmlPullParser parser = Xml.newPullParser();

然后我配置了char编码:

parser.setInput(<input stream>, "ISO-8859-15");

问题是此解析器不支持此char编码。这是抛出的异常:

org.xmlpull.v1.XmlPullParserException: Error parsing document. (position:line -1, column -1) caused by: org.apache.harmony.xml.ExpatParser$ParseException: At line 1, column 0: unknown encoding.

这真的很奇怪,因为我知道Android支持这种编码。证明这一行没有例外:

String test  = new String("hi".getBytes(), "ISO-8859-15");

但是,如果我将解析器配置为不同的编码,例如UTF-8或latin-1,它就可以工作。

我接下来尝试的是在Android中使用旧项目的解析器(kxml2),但后来我遇到了新的错误:

org.xmlpull.v1.XmlPullParserException: unexpected type (position:END_DOCUMENT null@9:1 in java.io.InputStreamReader@43e97088)

即使我可以毫无问题地使用它,kxml2在过去几年(2006年发布的最新版本)还没有得到支持,所以我想尽可能使用Android的pull解析器,这样更强大,也会有更好的表现。

我可以欺骗调用parser.setInput(bais, "ISO-8859-1");的默认解析器,因为这样它忽略了文件中XML声明中的编码,并且它起作用,因为两个字符集具有相同的字符数,并且大多数都是相同的。但是这样看待源代码的人可能会认为它实际上在拉丁语9中接收输入时会使用latin-1,因此会在latin-9中生成字符串。

默认的XML Pull Parser是否有任何理由不支持ISO-8859-15?是否有任何替代的PULL解析库具有良好的字符编码支持?

提前致谢。


更新:当我写这个问题时,我已经测试了OS 2.2和2.3中的默认解析器。但是,阅读Xml.newPullParser的javadoc我发现了这个:

  

注意:这实际上比SAX解析器慢,并且没有完全实现。如果你需要一个快速的,大部分实现的拉解析器,请使用它。如果您需要完整的实现,请使用KXML。

事实上,在OS 4.x中测试默认解析器时,我得到了第二个例外。对于OS 4来说,内置解析器实际上是kxml !!

1 个答案:

答案 0 :(得分:0)

好吧,看起来很难找到一个好的XmlPullParser库,所以我将按照javadocs中Xml.newPullParser工厂方法的建议使用kxml的解析器。 (我没有在在线javadocs中找到这个注释,仅在eclipse的javadoc窗口中。也许我正在使用旧的javadocs,这个注释后来在Android开始使用kxml作为内置解析器后被删除了。)

对于使用kxml的解析器时引发的异常,这是:

org.xmlpull.v1.XmlPullParserException: unexpected type (position:END_DOCUMENT null@9:1 in java.io.InputStreamReader@43e97088)

原来这是我的代码造成的。在初始端口,我意识到在调用parser.nextText之后,包含在Froyo和Gingerbread中的Android内置解析器没有进入下一个标记。所以我在这里和那里添加了一些parser.nexTag行以使其工作。然后我再次切换到kXml但我保留了那些额外的行,这使得我的KXmlParser实例在处理文件末尾时陷入困境。在到达文件末尾后调用nextTag时抛出异常。这也在nextTag的文档中进行了解释:

  

如果是START_TAG或END_TAG ,则调用next()并返回事件,否则抛出异常