RSS阅读器(使用android解析技术解析网络中的xml文件并以列表的形式显示出来)

使用android解析技术解析网络中的xml文件并以列表的形式显示出来,实现效果如下:


首先在主要的xml中做好布局,代码如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ListView 
        android:id="@+id/itemlist"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        />

</RelativeLayout>

编写实体类RssFeed.java,代码如下:

package cn.bzu.saxparseraccess_listshow.entity;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

public class RssFeed {

       private String title;//标题
       
       private String pubdate;//发布日期
       
       private int itemCount;//用于计算列表的数目
       
       private List<RssItem> rssItems ;//用于描述列表  item
       
       public RssFeed() {
    	 //加入对象的创建
	     rssItems=new ArrayList<RssItem>();
	   }
       //返回列表的长度  添加RssItem条目
       public int addItem(RssItem item){
    	   rssItems.add(item);
    	   itemCount++;
    	   return itemCount;
       }
	   //根据下标获取RssItem
       public RssItem getItem(int location){
    	   return rssItems.get(location);
       }
       
       //为ListView 设置HashMap<String,Object>
       public List<HashMap<String, Object>> getAllItemsForListView(){
    	   
           List<HashMap<String,Object>> data=new ArrayList<HashMap<String,Object>>();
           
           int size=rssItems.size();
           
           for (int i = 0; i < size; i++) {
        	   
			HashMap<String, Object> item=new HashMap<String, Object>();
			
			item.put(RssItem.TITLE, rssItems.get(i).getTitle());
			item.put(RssItem.PUBDATE, rssItems.get(i).getPubdate());
			
		    data.add(item);
		   }
           return data;
       }

		public String getTitle() {
			return title;
		}
	
		public void setTitle(String title) {
			this.title = title;
		}
	
		public String getPubdate() {
			return pubdate;
		}
	
		public void setPubdate(String pubdate) {
			this.pubdate = pubdate;
		}
	
		public int getItemCount() {
			return rssItems.size();
		}
	
	
	
		public List<RssItem> getRssItems() {
			return rssItems;
		}

	
       
}                                

编写实体类RssItem.java,代码如下:

package cn.bzu.saxparseraccess_listshow.entity;

public class RssItem {

	public static final String TITLE="title";
	
	public static final String PUBDATE="pubdate";
	
	private String title;
	
	private String description;
	
	private String link;
	
	private String category;
	
	private String pubDate;
	
	public RssItem() {
		
	}

	public String getTitle() {
		
		if(title.length()>20){
			return title.substring(0, 19)+"...";
		}
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public String getLink() {
		return link;
	}

	public void setLink(String link) {
		this.link = link;
	}

	public String getCategory() {
		return category;
	}

	public void setCategory(String category) {
		this.category = category;
	}

	public String getPubdate() {
		return pubDate;
	}

	public void setPubdate(String pubDate) {
		this.pubDate = pubDate;
	}

	@Override
	public String toString() {
		return "RssItem [title=" + title + ", description=" + description
				+ ", link=" + link + ", category=" + category + ", pubdate="
				+ pubDate + "]";
	}
	
}
编写RssFeed_SAXParser.java,代码如下:

package cn.bzu.saxparseraccess_listshow.saxparser;

import java.net.MalformedURLException;
import java.net.URL;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
import org.xml.sax.XMLReader;

import cn.bzu.saxparseraccess_listshow.entity.RssFeed;
import cn.bzu.saxparseraccess_listshow.service.RssHandler;

public class RssFeed_SAXParser {

	public RssFeed getFeed(String urlStr) throws MalformedURLException, Exception, SAXException{//需要穿一个URL地址
		
	    URL url=new URL(urlStr);
	    System.out.println("RssFeed_SAXParser-->url:"+url);
	    SAXParserFactory parserFactory=SAXParserFactory.newInstance();//构建sax解析工厂
	    SAXParser saxParser=parserFactory.newSAXParser();//解析工厂生产解析器
	    XMLReader xmlReader=saxParser.getXMLReader();//通过saxParser构建xmlReader阅读器
	    //构建自定义的xml解析器 作为 xmlReader的处理器(代理)
	    RssHandler rssHandler=new RssHandler();
	    
	    xmlReader.setContentHandler(rssHandler);
	    //使用url打开流,并将流作为 xmlReader解析的输入源并解析
	    InputSource is=new InputSource(url.openStream());
	    
	    xmlReader.parse(is);
	    
	    return rssHandler.getRssFeed();
	}
}
在service层中编写RssHandler.java,代码如下:

package cn.bzu.saxparseraccess_listshow.service;

import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;

import android.util.Log;

import cn.bzu.saxparseraccess_listshow.entity.RssFeed;
import cn.bzu.saxparseraccess_listshow.entity.RssItem;

public class RssHandler extends DefaultHandler {

	RssFeed rssFeed;// 用于保存解析过程中的channel
	RssItem rssItem;// 用于保存解析过程中的item

	String lastElementName = "";// 标记变量,用于标记在解析过程中我们关心的几个标签,若不是我们关心的标签记做0

	final int RSS_TITLE = 1;// 若是 title 标签,记做1,注意有两个title,但我们都保存在item的成员变量中
	final int RSS_LINK = 2;// 若是 link 标签,记做2
	final int RSS_DESCRIPTION = 3;// 若是 description 标签,记做3
	final int RSS_CATEGORY = 4;// 若是category标签,记做 4
	final int RSS_PUBDATE = 5; // 若是pubdate标签,记做
								// 5,注意有两个pubdate,但我们都保存在item的pubdate成员变量中

	int currentstate = 0;

	public RssHandler() {

	}

	// 下面通过重载 DefaultHandler 的 5 个方法来实现 sax 解析

	// 1. 这个方法在解析xml文档的一开始执行,一般我们需要在该方法中初始化解析过程中有可能用到的变量
	@Override
	public void startDocument() throws SAXException {

		super.startDocument();

		rssFeed = new RssFeed();

        rssItem = new RssItem();  


	}

	// 2. 当遇到文本结点时进行处理,空白符不用做处理,只需要对字符做处理
	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		super.characters(ch, start, length);
		// 获取字符串
		String text = new String(ch, start, length);
		Log.i("i", "要获取的内容:"+text);
		// 判断当前标志位 与那一种标志相同,然后做相应处理
		switch (currentstate) {
		case RSS_TITLE:
			rssItem.setTitle(text);
			currentstate = 0;// 设置完后,重置为开始状态
			break;
		case RSS_PUBDATE:
			rssItem.setPubdate(text);
			currentstate = 0;// 设置完后,重置为开始状态
			break;
		case RSS_CATEGORY:
			rssItem.setCategory(text);
			currentstate = 0;// 设置完后,重置为开始状态
			break;
		case RSS_LINK:
			rssItem.setLink(text);
			currentstate = 0;// 设置完后,重置为开始状态
			break;
		case RSS_DESCRIPTION:
			rssItem.setDescription(text);
			currentstate = 0;// 设置完后,重置为开始状态
			break;
		default:
			break;
		}
	}

	/**
	 * 3. 这个方法在解析标签开始标记时执行,一般我们需要在该方法取得标签属性值,但由于我们的rss文档
	 * 中并没有任何我们关心的标签属性,因此我们主要在这里进行的是设置标记变量currentstate, 以 标记我们处理到哪个标签
	 */
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		super.startElement(uri, localName, qName, attributes);
		// localName:不含命名空间前缀的标签名(建议使用)
		// qName:含有命名空间前缀的标签名
		// attributes:接收属性值
		if ("chanel".equals(localName)) {// 这个标签内没有我们关心的内容,所以不作处理,currentState=0

			currentstate = 0;
			return;
		}
		if ("item".equals(localName)) {

			/*
			 * 若是item标签,则重新构造一个RSSItem,从而把已有(已经解析过的)item数据扔掉, 当
			 * 然事先是已经保存到rssFeed的itemlist集合中
			 */
			rssItem = new RssItem();
			return;
		}
		if ("title".equals(localName)) {

			// 若是title标签,置currentstate为1,表明这是我们关心的数据,
			// 这样在characters 方法中会把元素内容保存到rssItem变量中
			currentstate = RSS_TITLE;
			return;
		}
		if ("description".equals(localName)) {

			currentstate = RSS_DESCRIPTION;
			return;
		}
		if ("link".equals(localName)) {

			currentstate = RSS_LINK;
			return;
		}
		if ("pubdate".equals(localName)) {

			currentstate = RSS_PUBDATE;
			return;
		}
		if ("category".equals(localName)) {

			currentstate = RSS_CATEGORY;
			return;
		}
	}

	// 4. 结束元素节点
	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {

		super.endElement(uri, localName, qName);

		// 如果解析一个item节点结束,就将rssItem添加到rssFeed中。
		if ("item".equals(localName)) {

			rssFeed.addItem(rssItem);
			return;
		}
	}

	@Override
	public void endDocument() throws SAXException {

		super.endDocument();

		// 这个方法在整个xml文档解析结束时执行,一般需要在该方法中返回或保存整个文档解析解析结果,

		// 但由于我们已经在解析过程中把结果保持在rssFeed中,所以这里什么也不做
	}

	public RssFeed getRssFeed() {
		return rssFeed;
	}

}
在主要的Activity中编写如下代码:

package cn.bzu.saxparseraccess_listshow.activity;

import java.net.MalformedURLException;

import org.xml.sax.SAXException;

import cn.bzu.saxparseraccess_listshow.activity.R;
import cn.bzu.saxparseraccess_listshow.entity.RssFeed;
import cn.bzu.saxparseraccess_listshow.entity.RssItem;
import cn.bzu.saxparseraccess_listshow.saxparser.RssFeed_SAXParser;
import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.SimpleAdapter;

public class MainActivity extends Activity implements OnItemClickListener{
	// 从网络获取RSS地址
	public final String RSS_URL = "http://blog.sina.com.cn/rss/1267454277.xml";

	public final String tag = "RSSReader";
	private RssFeed feed = null;

	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		setContentView(R.layout.activity_main);
		try {// 调用getFeed方法,从服务器取得rss提要
			feed = new RssFeed_SAXParser().getFeed(RSS_URL);
		} catch (MalformedURLException e) {

			e.printStackTrace();
		} catch (SAXException e) {

			e.printStackTrace();
		} catch (Exception e) {

			e.printStackTrace();
		}

		showListView(); // 把rss内容绑定到ui界面进行显示
	}




	private void showListView() {
		ListView itemlist = (ListView) findViewById(R.id.itemlist);
		if (feed == null) {
			setTitle("访问的RSS无效");
			return;
		}

		SimpleAdapter adapter = new SimpleAdapter(this,
				feed.getAllItemsForListView(),
				android.R.layout.simple_list_item_2, new String[] {
						RssItem.TITLE, RssItem.PUBDATE }, new int[] {
						android.R.id.text1, android.R.id.text2 });
		itemlist.setAdapter(adapter); // listview绑定适配器
		itemlist.setOnItemClickListener(this); // 设置itemclick事件代理
		itemlist.setSelection(0);

	}

	public void onItemClick(AdapterView parent, View v, int position, long id) // itemclick事件代理方法
	{
		Intent itemintent = new Intent(this, ActivityShowDescription.class);// 构建一个“意图”,用于指向activity
																			// :detail
		Bundle b = new Bundle(); // 构建buddle,并将要传递参数都放入buddle
		b.putString("title", feed.getItem(position).getTitle());
		b.putString("description", feed.getItem(position).getDescription());
		b.putString("link", feed.getItem(position).getLink());
		b.putString("pubdate", feed.getItem(position).getPubdate());
		itemintent.putExtra("android.intent.extra.rssItem", b); // 用android.intent.extra.INTENT的名字来传递参数
		startActivityForResult(itemintent, 0);
	}

}
添加activity_activity_show_description.xml,代码如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <TextView
        android:id="@+id/content"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:layout_weight="1.0"
        android:autoLink="all"
        android:text="" />

    <Button
        android:id="@+id/back"
        android:layout_width="fill_parent"
        android:layout_height="wrap_content"
        android:text="返回" />

</LinearLayout>
添加新的Activity(ActivityShowDescription),代码如下:

package cn.bzu.saxparseraccess_listshow.activity;

import android.os.Bundle;
import android.app.Activity;
import android.content.Intent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.support.v4.app.NavUtils;

public class ActivityShowDescription extends Activity {

	public void onCreate(Bundle icicle) {
		super.onCreate(icicle);
		setContentView(R.layout.activity_activity_show_description);
		String content = null;
		Intent startingIntent = getIntent();

		if (startingIntent != null) {
			Bundle bundle = startingIntent
					.getBundleExtra("android.intent.extra.rssItem");
			if (bundle == null) {
				content = "不好意思程序出错啦";
			} else {
				content = bundle.getString("title") + "\n\n"
						+ bundle.getString("pubdate") + "\n\n"
						+ bundle.getString("description").replace('\n', ' ')
						+ "\n\n详细信息请访问以下网址:\n" + bundle.getString("link");
			}
		} else {
			content = "不好意思程序出错啦";
		}

		TextView textView = (TextView) findViewById(R.id.content);
		textView.setText(content);

		Button backbutton = (Button) findViewById(R.id.back);

		backbutton.setOnClickListener(new Button.OnClickListener() {
			public void onClick(View v) {
				finish();
			}
		});
	}

}








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值