这几天做了一个解析RSS的小东西时碰到了些问题,在这里纪录一下。
1.先说明一下碰到了问题是什么。
最开始本想做个很简单的小东西,在ANDROID下面用SAX解析RSS,
没想到SAX对SINA博客之类的用了[CDATA]的RSS解析得不完整,很多只解析出了一句。
(ps,不知道SINA这种RSS是不是标准的,也许这居于XML的东西根本就没个标准)
另外,SAX对非标准的RSS解析得更差,
这里的‘非标准RSS'是指没用[CDATA]直接在 description里面放上HTML TAG的那种。
具体的问题描述我引用下面一段话
引用
SAX处理完Element事件后, 紧接着会继续读取,并且交由characters进行处理内容.Character处理普通字符没有任何问题, 不会诱发任何监听事件. 而当遇到< [ ] 等字符时,又会触发一个新的characters事件, 也就是说, 如果你仅仅在 Characters 事件中进行处理保存数据(保存到一个变量中)的话, 是没有任何问题的, 只是遇到的时候, 发生了多次的Characters, 而你的代码上对事件的处理方式是一样的, 都是保存到变量中, 所以,变量中仅仅会保留最后一次赋值的数据. 最后一份数据正常情况下均是\n或者空格. 所以造成了,SAX无法读取CDATA数据的表象.
出自:http://www.lshine.com/index.php/2010/07/sax_cdata/comment-page-1/#comment-7226
这个博客是在刚才在重新搜索时找到的,他的分析和我之前判断的一样。
(这个SAX问题我还是没解决,显示的内容是比以前多了,但还是不完整)
当然,如果具体Parser过程有疑问,可以看这个SAX官方网站,看看原理,看看源码:
http://www.saxproject.org/about.html
(SAX最后一次更新是SAX 2.0.2 (sax2 r3),在27-April 2004…不知道ANDROID里面的是不是这个版本…)
2.再说一下怎么解决问题。
SAX不行就换别的,DOM和PullXmlParser都可以。
这里先介绍一个:
http://zhoujianghai.iteye.com/blog/755749
他的这个比我的好,我看sdk和那些Tutorials快一个月了,写个东西还不能得心应手,
真是差距啊……
人家总结的也好:
引用
1)RSS的文件结构和含义
2)解析xml文件的几种方式
3)android应用的结构和MVC模式
4)activity的生命周期,
activity之间通过intent通信,
handler消息机制,
自定义ListView,
LinearLayout、
RelativeLayout、
FrameLayout布局界面,
WebView显示网页。
android数据存储(SQLite3)的相关操作,
菜单和对话框、Toast的使用,
android的测试驱动, (!)
uses-permission权限配置
这些,我花了一个月都像是在盲人摸象,完全没个纲领去系统的学习。
对我而言,还应该加上多线程之类的比较基础的东西……
真的反思一下了……
最后贴个东西:
1.Android XML Parser Performance,性能分析。留着备用。
http://www.developer.com/ws/article.php/10927_3824221_2/Android-XML-Parser-Performance.htm
2.下面是另一个人的SAX和PullxmlParser的代码,我写的东西太差,就不拿出来丢人现眼了……
http://blog.chinaunix.net/u2/85805/showart_1678985.html
over.
1 楼 aa87963014 2010-11-26
CDATA 这个问题 我也遇到过,开始没有想到是android的原因
以为是开源代码的问题,也是盲人摸象 后来对比之后确定是 android api问题
之后改为其他的就好了
以为是开源代码的问题,也是盲人摸象 后来对比之后确定是 android api问题
之后改为其他的就好了
2 楼 lovext 2010-11-26
aa87963014 写道
CDATA 这个问题 我也遇到过,开始没有想到是android的原因
以为是开源代码的问题,也是盲人摸象 后来对比之后确定是 android api问题
之后改为其他的就好了
以为是开源代码的问题,也是盲人摸象 后来对比之后确定是 android api问题
之后改为其他的就好了
是的,用XmlPullParser就可以了.
但是解析CDATA ,或者”description里面直接是很多HTML TAG“的问题是SAX的处理方式造成的,我没用ANDROID自带的api,而是用的org.xml.sax,可以解析,但是只能出现一部分内容。
具体的分析在上面的说过了,但是那个连接里面提到的解决方法我试过了,仍然未能成功,有时间的话会继续研究。
3 楼 yxfcd 2010-12-08
其实解决方案是有的,假设带有html的内容在<desc> ... some html code ... </desc>
1. 定义一boolean flag和StringBuilder
2. 在startElement 中检测localName 是否为desc,若是,flag置真,初始化StringBuilder
3. 在endElement 中检测localName 是否为desc,若是,flag置假,取得StringBuilder的值,即为html的内容
4. 在characters 中,只要flag值为真,追加new String(ch, start, length)到StringBuilder
代码如下:
private boolean isDescStarted = false;
private StringBuilder textDesc = new StringBuilder();
public void startElement(String namespaceURI, String localName,String qName, Attributes atts) throws SAXException {
if (localName.equals("desc")){
isDescStarted = true;
textDesc = new StringBuilder();
return;
}
//...
}
public void endElement(String namespaceURI, String localName, String qName) throws SAXException{
if (localName.equals("desc")){
isDescStarted = false;
String desc = textDesc.toString();
return;
}
//...
}
public void characters(char ch[], int start, int length){
if (isDescStarted) {
textDesc.append(new String(ch, start, length));
}
//...
}
1. 定义一boolean flag和StringBuilder
2. 在startElement 中检测localName 是否为desc,若是,flag置真,初始化StringBuilder
3. 在endElement 中检测localName 是否为desc,若是,flag置假,取得StringBuilder的值,即为html的内容
4. 在characters 中,只要flag值为真,追加new String(ch, start, length)到StringBuilder
代码如下:
private boolean isDescStarted = false;
private StringBuilder textDesc = new StringBuilder();
public void startElement(String namespaceURI, String localName,String qName, Attributes atts) throws SAXException {
if (localName.equals("desc")){
isDescStarted = true;
textDesc = new StringBuilder();
return;
}
//...
}
public void endElement(String namespaceURI, String localName, String qName) throws SAXException{
if (localName.equals("desc")){
isDescStarted = false;
String desc = textDesc.toString();
return;
}
//...
}
public void characters(char ch[], int start, int length){
if (isDescStarted) {
textDesc.append(new String(ch, start, length));
}
//...
}