上次提到了用Pull的方法解析xml,這裏又遇到了另外一種用sax DefaultHandler處理類的方法解析xml。
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader xmlReader = parser.getXMLReader();
xmlReader.setContentHandler(mRSSHandler);
xmlReader.parse(new InputSource(mStream));
sax使用的工廠設計模式,通過,通過ASXParserFactory獲取解析器parser,再從解析器中獲得解析xml文件的xmlReader,但是在xmlReader讀取流式的xml文件時,需要完成一個RSSHandler的設置,它是繼承的DefalutHandler,這裏詳細介紹使用sax解析xml的DefaultHandler處理類。
下面是一個xml的文件格式:
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0">
<channel>
<item>
<title>Ubuntu11.04(10.04)安裝dos工具dosemu</title>
<link>http://www.ourunix.org/post/276.html</link>
<author>[email protected] (walfred)</author>
<category>玩轉Linux</category>
<pubDate>Mon, 16 Jan 2012 22:54:53 +0800</pubDate>
<comments />
<description>看完介紹之後,發現這是繼wine之後的有一款linux類win工具了,所以現在直接上文介紹dosemu在ubuntu Linux上的安裝步驟及使用其運行dos遊戲:魂鬥羅~~~</description>
</item>
</channel>
</rss>
RSSHandler繼承的DefaultHandler處理類就是專門來解析這個文件的,下面是必須完成的藉口:
public void startDocument () {
//開始解析文檔
}
public void endDocument () {
//文檔解析結束
}
public void startElement (String uri, String localName, String qName, Attributes attributes) {
//開始解析節點
}
public void characters (char[] ch, int start, int length) {
//保存節點內容
}
public void endElement (String uri, String localName, String qName) {
//結束解析節點
}
一共5個函數。
一般前兩個方法,開始解析和結束解析文檔不需要做處理外,我們的所有操作都是在解析節點部分,我們調用的startElement開始解析節點,then調用characters保存節點內容,最後調用endElement,如此循環。
示例:
public class RSSHandler extends DefaultHandler {
private Context mContext;
private RSSItem mRSSItem;
private RSSDBInterface mRSSDBInterface;
private final int TITLE_STATE = 1;
private final int AUTHOR_STATE = 2;
private final int LINK_STATE = 3;
private final int DESCRIPTION_STATE = 4;
private final int CATEGORY_STATE = 5;
private final int PUBDATE_STATE = 6;
//標記當前節點
private int currentState;
public RSSHandler(Context ctx){
mContext = ctx;
//初始化當前節點標記爲0
currentState = 0;
//數據庫接口
mRSSDBInterface = new RSSDBInterface(mContext);
}
public void startDocument () {
//開始解析文檔
mRSSItem = new RSSItem();
}
public void endDocument () {
//文檔解析結束
}
public void startElement (String uri, String localName, String qName, Attributes attributes) {
//開始解析節點
if (localName.equals("channel")){
return ;
}
if (localName.equals("item")){
//當遇到一個item節點時,就實例化一個RSSItem對象
mRSSItem = new RSSItem();
return;
}
if (localName.equals("title")){
currentState = TITLE_STATE;
return ;
}
if (localName.equals("author")){
currentState = AUTHOR_STATE;
return ;
}
if (localName.equals("description")){
currentState = DESCRIPTION_STATE;
return ;
}
if (localName.equals("link")){
currentState = LINK_STATE;
return ;
}
if (localName.equals("category")){
currentState = CATEGORY_STATE;
return ;
}
if (localName.equals("pubDate")){
currentState = PUBDATE_STATE;
return ;
}
}
public void endElement (String uri, String localName, String qName) {
//這是節點解析完成時調用的,這裏我們遇到item的時候才調用下面的
if(localName.equals("item" && mRSSItem != null)){
ContentValues values = new ContentValues();
values.put(RSSDBInfo.Columns._TITLE, mRSSItem.getTitle());
values.put(RSSDBInfo.Columns._AUTHOR, mRSSItem.getAuthor());
values.put(RSSDBInfo.Columns._CATEGORY, mRSSItem.getCategory());
values.put(RSSDBInfo.Columns._DESCRIPTION, mRSSItem.getDescription());
values.put(RSSDBInfo.Columns._LINK, mRSSItem.getLink());
values.put(RSSDBInfo.Columns._PUBDATE, mRSSItem.getPubdate());
values.put(RSSDBInfo.Columns._ISREAD, RSSUtils.ARTICALE_UNREAD);
mRSSDBInterface.insertRSStoDB(values);
}
}
public void characters (char[] ch, int start, int length) {
String theString = new String(ch, start, length);
switch(currentState){
case TITLE_STATE:
mRSSItem.setTitle(theString);
currentState = 0;
break;
case AUTHOR_STATE:
mRSSItem.setAuthor(theString);
currentState = 0;
break;
case LINK_STATE:
mRSSItem.setLink(theString);
currentState = 0;
break;
case DESCRIPTION_STATE:
mRSSItem.setDescription(theString);
currentState = 0;
break;
case CATEGORY_STATE:
mRSSItem.setCategory(theString);
currentState = 0;
break;
case PUBDATE_STATE:
mRSSItem.setPubdate(theString);
currentState = 0;
break;
}
}
}