Android分析 Sax解析xml文件时,遇到的not well-formed错误

由于sax是触发式的解析xml流, 在手持设备的系统中,应用相当广泛. 在android的应用开发中,自然也偏向于选择sax来解析xml了.
在做一份rss应用中,需要解析baidu.com的rss文件时遇到了not well-formed的错误. 查询了相关资料以及不断debug and log之后, 终于确定了是文件编码遇到了问题.
在此说下我的一些理解, 如有错误请留言指出
首先国内资讯内容提供商使用的rss编码各不相同 网易使用gb2312, 新浪utf-8, 百度GBK 等等.
1. 当URL请求rss.xml后, 通过openStream将返回一个InputStream的字节流对象, 字节流本身是不带编码信息的.
(ps. 为什么说字节流前3个字节,保存的是编码信息? 我通过测试byte[3]的数组,比对UTF8字节数组(-17,-69,-65) 无论是否是UTF8编码均不能匹配上)
2. 得到字节流后,通常是可以直接使用InputStream对象去生成一个InputSource对象,来给saxParser或者是XmlReader进行解析的. 默认的情况下, parser解析的InputSource对象是按照utf8编码方式的, 所以,在不做任何处理时, utf8编码的xml文件解析是正常的.
3. 当遇到Gbk,或者gb2312编码时,解析ANSI字符是没有问题的,解析到中文时,parser是按照默认的UTF8编码进行解析的, UTF8是每个字符分配3字节, gb2312是分配两字节,必然会造成错误.这时也就报出了not well-formed error.
当时注意到inputSource有个setEncoding的方法,是告诉sarpar使用何种编码去解析这个inputStream, 你可以设置使用GBK去解析这个stream, 但是资源文件的编码都是utf8,而你使用GBK去解析明显是不符合的.
4. SetEncoding是不会将编码进行转换的,仅仅是告诉sarpar如何去解析, 那么遇到xml encoding是gbk gb2312的情况下, 可以使用inputStreamReader的方式,
inputStreamReader(inputStream, charsetName)来指定编码生成字符流.这里显然发生了编码转换.
然后传递这个字符流对象到InputSource对象,这个对象在接受字符流时,是不能setEncoding的, 原因也很简单,字符流是带编码信息的,仍然不放心可以再次setEncoding,(不过是无效的)
5. 这样最后只要通过判别文件的编码方式,然后告诉sarpar如何去解析,程序就可以正常执行了.
识别字节流的编码方式可以google查询到很多方法,常用的是通过mozilla提供的一个开源工具来识别的. 目前最新为: cpdetector_1.0.8 可以在SourceForge下载到.
关键代码:

View Code JAVA1

XMLContentHandler handler = new XMLContentHandler();
XMLReader reader = null;
InputSource is = null;
try{  
URL url = new URL(w163); 
SAXParserFactory parserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = parserFactory.newSAXParser();
if(!isUTF8(url)){
InputStream stream = url.openStream();
InputStreamReader streamReader = new InputStreamReader(stream,"GBK");
is = new InputSource(streamReader);
}else{
is = new InputSource(url.openStream());
is.setEncoding("UTF-8");
}
reader = saxParser.getXMLReader();
reader.setContentHandler(handler);
}catch(Exception e){
Log.e(TAG, "Exception updateRss()");
}
try {
reader.parse(is);
} catch (IOException e) {
e.printStackTrace();
} catch (SAXException e) {
Log.e(TAG, e.getMessage());
        }


其中isUTF8是通过mozilla的jar包来实现的,具体可以参考cpdetector使用方法的相关文章.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android Studio 中,可以使用 SAX 解析解析 XML 文件。SAX 解析器是一种基于事件的解析器,它可以将 XML 文件解析为一系列事件,然后通过监听这些事件来获取所需的数据。 以下是使用 SAX 解析解析 XML 文件的示例代码: ```java public class MyHandler extends DefaultHandler { private String currentValue; private boolean parsingName; @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (localName.equals("name")) { parsingName = true; } } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if (parsingName) { // 处理姓名数据 parsingName = false; } } @Override public void characters(char[] ch, int start, int length) throws SAXException { if (parsingName) { currentValue = new String(ch, start, length); } } } // 在 Activity 中使用 SAX 解析器 try { InputStream inputStream = getResources().openRawResource(R.raw.my_xml_file); SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser saxParser = factory.newSAXParser(); MyHandler handler = new MyHandler(); saxParser.parse(inputStream, handler); } catch (Exception e) { e.printStackTrace(); } ``` 在上面的示例代码中,MyHandler 类继承了 DefaultHandler 类,并重写了 startElement()、endElement() 和 characters() 方法来监听 XML 文件中的事件。在 startElement() 方法中,可以判断当前解析的标签是否是所需的标签,并进行相应的处理;在 endElement() 方法中,可以完成对标签数据的处理;在 characters() 方法中,可以获取标签文本内容。 在 Activity 中,可以使用 SAXParserFactory 类和 SAXParser 类来创建和使用 SAX 解析器。在调用 saxParser.parse() 方法,需要传入要解析XML 文件的输入流和事件处理器。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值