1. 简介

1). SAX,全称Simple API for XML,是一种基于事件的解析器。

SAX采用事件驱动机制来解析XML文档。什么是事件驱动模式?它将XML文档转换成一系列的事件,由单独的事件处理器来决定如何处理。

每当SAX解析器发现文档开始、元素开始、文本、元素结束、文档结束等事件时,就会向外发送一次事件,而开发者则可以通过编写事件监听器处理这些事件,以此来获取XML文档里的信息。

工作原理: 就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。

DOM也可以用来解析XML文件

  DOM标准简单易用,但是它需要一次性地读取整个XML文档,而且在程序运行期间,整个DOM树常驻内存,导致系统开销过大。SAX解析方式占用内存小,处理速度更快。由于DOM一次性将整个XML文档全部读入内存,因此可以随机访问XML文档的每个元素。SAX采用顺序模式来依次读取XML文档,因此无法做到随机访问XML文档的任意元素

2). 实现过程

(一)第一步:新建一个工厂类SAXParserFactory,代码如下:

SAXParserFactory factory = SAXParserFactory.newInstance();

(二)第二步:让工厂类产生一个SAX的解析类SAXParser,代码如下:

SAXParser parser = factory.newSAXParser();

(三)第三步:从SAXPsrser中得到一个XMLReader实例,代码如下:

XMLReader reader = parser.getXMLReader();

(四)第四步:把自己写的handler注册到XMLReader中,一般最重要的就是ContentHandler,代码如下:

RSSHandler handler = new RSSHandler(); reader.setContentHandler(handler);

(五)第五步:将一个xml文档或者资源变成一个java可以处理的InputStream流后,解析正式开始,代码如下:

parser.parse(is);

下面来介绍具体的实现:

 1). 首先新建一个XML文件,如下:

<?xml version="1.0" encoding="UTF-8"?>
    <channel>
        <title>RSS 解析练习</title>
        <description>hehehaha</description>
        <link>http://www.cnblogs.com/felix-hua/</link>
        <language>zh-cn</language>

        <item>
            <title><![CDATA[头条]]></title>
            <link>http://mc.cz001.com.cn/images/menu/23_active.png</link>
            <category>0</category>
            <description>描述详细信息的</description>
            <pubDate>2012-01-09</pubDate>
        </item>
        
        <item>
            <title><![CDATA[新闻]]></title>
            <link>http://mc.cz001.com.cn/images/menu/23_active.png</link>
            <category>0</category>
            <description>描述详细信息的</description>
            <pubDate>2012-01-09</pubDate>
        </item>
        
        <item>
            <title><![CDATA[社会]]></title>
            <link>http://mc.cz001.com.cn/images/menu/23_active.png</link>
            <category>0</category>
            <description>描述详细信息的</description>
            <pubDate>2012-01-09</pubDate>
        </item>
        
        <item>
            <title><![CDATA[财经]]></title>
            <link>http://mc.cz001.com.cn/images/menu/23_active.png</link>
            <category>0</category>
            <description>描述详细信息的</description>
            <pubDate>2012-01-09</pubDate>
        </item>
 
  </channel>
        
View Code

 2). 一般解析一个XML文件都会对应到实体类中,因此为上面XML文件设计两个实体类,命名为:RSSItem, RSSFile,代码如下:

  RSSItem代码如下:

 1 package com.bing.file;
 2 
 3 public class RSSItem {
 4     
 5     public static final String CHANNEL = "channel";
 6     public static final String ITEM = "item";
 7     public static final String TITLE = "title";
 8     public static final String LINK = "link";
 9     public static final String CATAGORY = "category";
10     public static final String DESCRIPTION = "description";
11     public static final String PUBDATE = "pubDate";
12     
13     public static final int RSS_CHANNEL = 0;
14     public static final int RSS_TITLE = 1;
15     public static final int RSS_LINK = 2;
16     public static final int RSS_CATEGORY = 3;
17     public static final int RSS_DESCRIPTION = 4;
18     public static final int RSS_PUBDATE = 5;
19     
20     private String title;
21     
22     private String link;
23     
24     private String catagory;
25     
26     private String description;
27     
28     private String pubDate;
29 
30     public RSSItem(){
31         
32     }
33     
34     public String getTitle(){
35         return title;
36     }
37     
38     public void setTitle(String title) {
39         this.title = title;
40     }
41 
42     public String getLink() {
43         return link;
44     }
45 
46     public void setLink(String link) {
47         this.link = link;
48     }
49 
50     public String getCatagory() {
51         return catagory;
52     }
53 
54     public void setCatagory(String catagory) {
55         this.catagory = catagory;
56     }
57 
58     public String getDescription() {
59         return description;
60     }
61 
62     public void setDescription(String description) {
63         this.description = description;
64     }
65 
66     public String getPubDate() {
67         return pubDate;
68     }
69 
70     public void setPubDate(String pubDate) {
71         this.pubDate = pubDate;
72     }
73 
74 }
View Code

     RSSFile代码如下:

 1 package com.bing.file;
 2 
 3 import java.util.ArrayList;
 4 import java.util.HashMap;
 5 
 6 import android.graphics.drawable.shapes.RoundRectShape;
 7 
 8 public class RSSFile {
 9     
10     private ArrayList<RSSItem> rssFiles = new ArrayList<RSSItem>();
11     
12     public RSSFile(){
13         
14     }
15     
16     public ArrayList<RSSItem> getRssFiles() {
17         return rssFiles;
18     }
19 
20     public void setRssFiles(ArrayList<RSSItem> rssFiles) {
21         this.rssFiles = rssFiles;
22     }
23 
24     //获取items数量
25     public int rssCount(){
26         
27         return rssFiles.size();
28     }
29     
30     //获取某一条Item信息
31     public RSSItem getRssItem(int position){
32         
33         return rssFiles.get(position);
34     }
35     
36     //添加一条Item
37     public void addItem(RSSItem item){
38         rssFiles.add(item);
39     }
40     
41     /*
42      * 负责从RSSFeed类中生成列表所需要的数据
43      * return
44      */
45     public ArrayList<HashMap<String, String>> getAllRecordList(){
46         
47         ArrayList<HashMap<String, String>> data = new ArrayList<HashMap<String,String>>();
48         
49         for(int i = 0; i < rssFiles.size(); i++){
50             HashMap<String, String> item = new HashMap<String, String>();
51             item.put(RSSItem.TITLE, rssFiles.get(i).getTitle());
52             item.put(RSSItem.PUBDATE, rssFiles.get(i).getPubDate());
53             data.add(item);
54         }
55         
56         return data;
57     }
58     
59     
60 
61 }
View Code

 3). 完成实体类后,下一步就要写核心处理类,即:RSSHandler,它继承自DefaultHandler,需要重写startDocument,endDocument,startDocument,endElement,characters这五个方法

  1 package com.bing.file;
  2 
  3 import java.util.ArrayList;
  4 
  5 import org.xml.sax.Attributes;
  6 import org.xml.sax.SAXException;
  7 import org.xml.sax.helpers.DefaultHandler;
  8 
  9 public class RSSHandler extends DefaultHandler {
 10     
 11     private RSSItem rssItem = null;
 12     private RSSFile rssFile = null;
 13     
 14     private ArrayList<RSSFile> rssList = null;
 15     private int currentTAG;
 16     
 17     
 18     public RSSHandler() {
 19         // TODO Auto-generated constructor stub
 20         rssItem = new RSSItem();
 21         rssFile = new RSSFile();
 22     }
 23     
 24     
 25     public RSSFile getRSSFile(){
 26         return rssFile;
 27     }
 28     
 29     
 30     /** 
 31      * 当SAX解析器解析到XML文档开始时,会调用的方法 
 32      */ 
 33     @Override
 34     public void startDocument() throws SAXException {
 35         // TODO Auto-generated method stub
 36         System.out.println("开始解析");
 37     }
 38     
 39     
 40     /** 
 41      * 当SAX解析器解析到XML文档结束时,会调用的方法 
 42      */ 
 43     @Override
 44     public void endDocument() throws SAXException {
 45         // TODO Auto-generated method stub
 46         System.out.println("解析完成");
 47     }
 48 
 49     
 50      /** 
 51      * 当SAX解析器解析到某个元素开始时,会调用的方法 
 52      * 其中localName记录的是元素属性名 
 53      */  
 54     @Override  
 55     public void startElement(String uri, String localName, String qName,
 56             Attributes attributes) throws SAXException {
 57         // TODO Auto-generated method stub
 58         
 59         if(localName.equals(RSSItem.CHANNEL)){
 60             currentTAG = RSSItem.RSS_CHANNEL;
 61             return;
 62         }
 63         if(localName.equals(RSSItem.ITEM)){
 64             rssItem = new RSSItem();
 65             return;
 66         }
 67         if(localName.equals(RSSItem.TITLE)){
 68             currentTAG = RSSItem.RSS_TITLE;
 69             return;
 70         }
 71         if(localName.equals(RSSItem.LINK)){
 72             currentTAG = RSSItem.RSS_LINK;
 73             return;
 74         }
 75         if(localName.equals(RSSItem.CATAGORY)){
 76             currentTAG = RSSItem.RSS_CATEGORY;
 77             return;
 78         }
 79         if(localName.equals(RSSItem.DESCRIPTION)){
 80             currentTAG = RSSItem.RSS_DESCRIPTION;
 81             return;
 82         }
 83         if(localName.equals(RSSItem.PUBDATE)){
 84             currentTAG = RSSItem.RSS_PUBDATE;
 85             return;
 86         }
 87         currentTAG = RSSItem.RSS_CHANNEL;
 88         
 89         System.out.println("处理标签");
 90     }
 91     
 92     
 93     /** 
 94      * 当SAX解析器解析到某个元素结束时,会调用的方法 
 95      * 其中localName记录的是元素属性名 
 96      */  
 97     @Override
 98     public void endElement(String uri, String localName, String qName)
 99             throws SAXException {
100         if(localName.equals("item")){
101             rssFile.addItem(rssItem);
102         }
103     }
104     
105     /** 
106      * 当SAX解析器解析到某个属性值时,会调用的方法 
107      * 其中参数ch记录了这个属性值的内容 
108      */  
109     @Override
110     public void characters(char[] ch, int start, int length)
111             throws SAXException {
112         
113         String content = new String(ch, start, length);
114         switch(currentTAG){
115             case RSSItem.RSS_TITLE:
116                 rssItem.setTitle(content);
117                 currentTAG = RSSItem.RSS_CHANNEL;
118                 break;
119             case RSSItem.RSS_LINK:
120                 rssItem.setLink(content);
121                 currentTAG = RSSItem.RSS_CHANNEL;
122                 break;
123             case RSSItem.RSS_CATEGORY:
124                 rssItem.setCatagory(content);
125                 currentTAG = RSSItem.RSS_CHANNEL;
126                 break;
127             case RSSItem.RSS_DESCRIPTION:
128                 rssItem.setDescription(content);
129                 currentTAG = RSSItem.RSS_CHANNEL;
130                 break;
131             case RSSItem.RSS_PUBDATE:
132                 rssItem.setPubDate(content);
133                 currentTAG = RSSItem.RSS_CHANNEL;
134                 break;
135             default:
136                 return;
137         }
138         
139     }
140     
141 
142 }
View Code

4).最后,在界面显示XML
  main.xml布局如下,没有可说的

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context="com.bing.saxtest.MainActivity" >
10 
11     <ListView 
12         android:id="@+id/android:rsslist"
13         android:layout_width="fill_parent"
14         android:layout_height="fill_parent"
15         />
16 
17 </RelativeLayout>
View Code

 main类

 1 package com.bing.saxtest;
 2 
 3 import java.io.IOException;
 4 import javax.xml.parsers.ParserConfigurationException;
 5 import javax.xml.parsers.SAXParser;
 6 import javax.xml.parsers.SAXParserFactory;
 7 
 8 import org.xml.sax.InputSource;
 9 import org.xml.sax.SAXException;
10 import org.xml.sax.XMLReader;
11 
12 import android.app.Activity;
13 import android.os.Bundle;
14 import android.util.Log;
15 import android.widget.ListView;
16 import android.widget.SimpleAdapter;
17 
18 import com.bing.file.RSSFile;
19 import com.bing.file.RSSHandler;
20 import com.bing.file.RSSItem;
21 
22 
23 public class MainActivity extends Activity {
24     
25     private static final String TAG = "MainActivity";
26     
27     private static final String XMLPATH = "xml/test.xml";
28     
29     private ListView list;
30     
31     private RSSHandler rssHandler;
32     
33     private RSSFile rssFile = null;
34 
35     @Override
36     protected void onCreate(Bundle savedInstanceState) {
37         super.onCreate(savedInstanceState);
38         setContentView(R.layout.activity_main);
39         
40         initData();
41         
42         showList();
43         
44     }
45 
46     private void initData(){
47         
48         SAXParserFactory factory = SAXParserFactory.newInstance();
49         try {
50             SAXParser parser = factory.newSAXParser();
51             XMLReader reader = parser.getXMLReader();
52             
53             rssHandler = new RSSHandler();
54             reader.setContentHandler(rssHandler);
55             
56             InputSource input = new InputSource(this.getResources().getAssets().open(XMLPATH));
57             reader.parse(input);
58             
59             rssFile = rssHandler.getRSSFile();
60             
61         } catch (ParserConfigurationException e) {
62             e.printStackTrace();
63         } catch (SAXException e) {
64             e.printStackTrace();
65         } catch (IOException e) {
66             e.printStackTrace();
67         }
68         
69     }
70     
71 
72     private void showList(){
73          list = (ListView) findViewById(R.id.android_rsslist);
74          
75          Log.i(TAG, rssFile.rssCount() + "");
76          SimpleAdapter adapter = new SimpleAdapter(this, rssFile.getAllRecordList(), android.R.layout.simple_list_item_2, 
77                  new String[]{RSSItem.TITLE, RSSItem.PUBDATE}, new int[]{android.R.id.text1, android.R.id.text2}
78                  );
79          
80          list.setAdapter(adapter);
81          
82     }
83     
84 
85     
86 }
View Code

5). 结果显示

 

参考文献:

1. http://www.cnblogs.com/felix-hua/archive/2012/01/10/2317404.html

 

posted on 2015-04-30 19:02  tiandibing  阅读(243)  评论(0编辑  收藏  举报