Monday, January 14, 2013

[Android] RSS Reader(利用SAX解析XML)

http://j796160836.pixnet.net/blog/post/30533118

http://j796160836.pixnet.net/blog/post/31555925

http://j796160836.pixnet.net/blog/post/31555937

http://14815011.blog.hexun.com.tw/56562721_d.html

http://rritw.com/a/bianchengyuyan/xml/2012/1215/272472.html

http://rritw.com/a/bianchengyuyan/xml/2011/1111/141622.html

在Android的XML解析上有兩種方式
1.DOM(Document Object Model),他會把整份XML檔案載入,然後成為一個樹狀物件

2.SAX(Simple API for XML),照順序從頭往下讀,其中讀到一個節點、屬性.....等,就採用事件的方式來處理

很多效能測試上,SAX比DOM更有效率

像一個旅遊新聞RSS大概長這樣(以下有部分元素省略)
http://tw.news.yahoo.com/rss/travel








旅遊新聞 - 頭條新聞 - Yahoo!奇摩新聞

http://tw.new.yahoo.com/travel

(...略)

zh-Hant-TW

Sun, 06 Jan 2013 05:30:00 +0800

5



冬日泡湯香港客愛北投

http://te.new.yahoo.com/(...略)-024412185.html

Sun, 06 Jan 2013 10:44:12 +0800

(...略)







RSS是照著XML的格式規範走的 開頭第一行就有XML的宣告,之後的內容就跟HTML感覺很像   文件中包含了RSS的channel(頻道),頻道的名字、連結、頻道介紹、語言別、更新日期....等   item裡面的東西比較重要,代表一個RSS項目(也許是一篇文章或是新聞),他的標題、連結、時間、簡介...等    



Java & XML學習筆記


1、需要軟件

java,解析器(例如Xerces),API(例如SAX,DOM)

2、SAX機制

1)解析

String xmlURI = "c:/test.xml";

String vendorParserClass = "org.apache.xerces.parsers.SAXParser";

XMLReaer reader = XMLReaderFactory.createXMLReader(vendorParserClass);



InputSource inputSource = new InputSource(xmlURI);

reader.parse(inputSource);



這樣一個xml文檔解析過程就完成了。因為SAX是採用時間處理機制來解析XML

文檔的,在解析過程中會觸發一些事件,也就是執行特定的方法,你可以實現

這些方法,就可以通過解析xml來做一些事情了

2)處理

SAX2.0定義的核心處理接口一共有

org.xml.sax.ContentHandler

org.xml.sax.ErrorHandler

org.xml.sax.DTDHandler

org.xml.sax.EntityResolver

這些接口是通過

org.xml.sax.XMLReader的setContentHandler(),setEroorHandler(),

setDTDHandler(),setEntityHandler()註冊到解析器,這裡面最重要的是

org.xml.sax.ContentHandler接口,它具體如下

public interface ContentHandler{

public void setDocumentLocator(Locator locator);

public void startDocument() throws SAXException;

public void endDocument() throws SAXException;

public void startPrefixMapping(String prefix,String uri)

throws SAXException;

public void endPrefixMapping(String prifix)

throws SAXException;

public void startElement(String namespaceURI,String localName,

String qName,Attributes atts) throws SAXException;

public void endElement(String namespaceURI,String localName,

String qName) throws SAXException;

public void characters(char ch[],int start,int length)

throws SAXException;

public void ignorableWhitespace(char ch[],int start,int length)

throws SAXException;

public void processingInstruction(String target,String data)

throws SAXException;

public void skippedEntity(String name)

throws SAXException;

}

通過setContentHandler()將你實現的ContentHandler註冊給XMLReader之後,

在解析過程中,系統根據各種條件執行接口中的方法,下面簡單說明一下

1)文檔定位器

private Locator locator;



public void setDocumentLocator(Locator locator){

this.locator = locator;

}



通常情況下,你只要如此實現就可以了,這個主要是得到當前解析的位置,

通過得到的locator,你可以使用它的getLineNumber(),getColumnName()等

方法,可以得到文檔當前的位置,但要注意的是,這個locator不能保存,只

針對當前的解析有效

2)文檔的開頭和結尾

public void startDocument() throws SAXException{

//解析過程中僅位於setDocumentLocator()方法後調用

}

public void endDocument() throws SAXException{

//解析過程中最後調用

}



大多數情況下你可以不用理他們,只要寫個空方法就可以了

3)名字空間的開始和結束

public void startPrefixMapping(String prefix,String uri)

throws SAXException{

}

public void endPrefixMapping(String prifix)

throws SAXException{

}

4)元素的開始和結束

public void startElement(String namespaceURI,String localName,

String qName,Attributes atts) throws SAXException{

}

public void endElement(String namespaceURI,String localName,

String qName) throws SAXException{

}

5)元素的數據

public void characters(char ch[],int start,int length)

throws SAXException{

String s = new String(ch,start,length);

}

這個是得到當前的元素的文本數據

6)可以忽略的空白

public void ignorableWhitespace(char ch[],int start,int length)

throws SAXException{

}

7)實體

public void skippedEntity(String name)

throws SAXException{

}

8)指令處理

public void processingInstruction(String target,String data)

throws SAXException{

}

3)例子:這個是從Java & XML 中複製過來的,

/*

* Created on 2004-11-30

*

* TODO To change the template for this generated file go to

* Window - Preferences - Java - Code Style - Code Templates

*/

package javaxml2;



/**

* @author yuangfang

*

* TODO To change the template for this generated type comment go to

* Window - Preferences - Java - Code Style - Code Templates

*/



import java.io.*;

import java.util.*;

import org.xml.sax.*;

import org.xml.sax.ext.LexicalHandler;

import org.xml.sax.helpers.XMLReaderFactory;



import java.awt.*;

import javax.swing.*;

import javax.swing.tree.*;



public class SAXTreeViewer extends JFrame{



private String vendorParserClass = "org.apache.xerces.parsers.SAXParser";



private JTree jTree;

DefaultTreeModel defaultTreeModel;



public SAXTreeViewer(){

super("SAX Tree Viewer");

setSize(600,450);

}



public void init(String xmlURI) throws IOException,SAXException{

DefaultMutableTreeNode base = new DefaultMutableTreeNode("XML Document:" + xmlURI);

defaultTreeModel = new DefaultTreeModel(base);

jTree = new JTree(defaultTreeModel);



buildTree(defaultTreeModel,base,xmlURI);

getContentPane().add(new JScrollPane(jTree),BorderLayout.CENTER);



}



public void buildTree(DefaultTreeModel treeModel,DefaultMutableTreeNode base,String xmlURI)

throws IOException,SAXException{



String featureURI = "";

try{

XMLReader reader = XMLReaderFactory.createXMLReader(vendorParserClass);



ContentHandler jTreeContentHandler = new JTreeContentHandler(treeModel,base);

ErrorHandler jTreeErrorHandler = new JTreeErrorHandler();



reader.setContentHandler(jTreeContentHandler);

reader.setErrorHandler(jTreeErrorHandler);

reader.setEntityResolver(new SimpleEntityResolver());



featureURI = "http://xml.org/sax/features/validation";

reader.setFeature(featureURI,true);



featureURI = "http://xml.org/sax/features/namespaces";

setNamespaceProcessing(reader,true);



featureURI = "http://xml.org/sax/features/string-interning";

reader.setFeature(featureURI,true);



featureURI = "http://apache.org/xml/features/validation/schema";

reader.setFeature(featureURI,false);



InputSource inputSource = new InputSource(xmlURI);

reader.parse(inputSource);

}

catch(SAXNotRecognizedException e){

System.out.println("The parse class " + vendorParserClass

+ " does not recognize the feature URI " + featureURI);

System.exit(0);

}

catch(SAXNotSupportedException e){

System.out.println("The parser class " + vendorParserClass +

" does not support the feature URI " + featureURI);

}

}



private void setNamespaceProcessing(XMLReader reader,boolean state)

throws SAXNotSupportedException,SAXNotRecognizedException

{

reader.setFeature("http://xml.org/sax/features/namespaces",state);

reader.setFeature("http://xml.org/sax/features/namespace-prefixes",!state);

}

public static void main(String[] args) {

try{

if(args.length != 1){

System.out.println("Usage:Java javaxml2.SAXTreeViewer " + "[XML Document URI]");

System.exit(0);

}

SAXTreeViewer viewer = new SAXTreeViewer();

viewer.init(args[0]);

viewer.setVisible(true);

}catch(Exception e)

{

e.printStackTrace();

}

}

}



class JTreeContentHandler implements ContentHandler,LexicalHandler{

private DefaultTreeModel treeModel;



private DefaultMutableTreeNode current;



private Locator locator;



private Map namespaceMappings;



/* (non-Javadoc)

* @see org.xml.sax.ext.LexicalHandler#comment(char[], int, int)

*/

public void comment(char[] ch, int start, int length) throws SAXException {

// TODO Auto-generated method stub



}

/* (non-Javadoc)

* @see org.xml.sax.ext.LexicalHandler#endCDATA()

*/

public void endCDATA() throws SAXException {

// TODO Auto-generated method stub



}

/* (non-Javadoc)

* @see org.xml.sax.ext.LexicalHandler#endDTD()

*/

public void endDTD() throws SAXException {

// TODO Auto-generated method stub



}

/* (non-Javadoc)

* @see org.xml.sax.ext.LexicalHandler#endEntity(java.lang.String)

*/

public void endEntity(String name) throws SAXException {

// TODO Auto-generated method stub

current = (DefaultMutableTreeNode)current.getParent();

}

/* (non-Javadoc)

* @see org.xml.sax.ext.LexicalHandler#startCDATA()

*/

public void startCDATA() throws SAXException {

// TODO Auto-generated method stub



}

/* (non-Javadoc)

* @see org.xml.sax.ext.LexicalHandler#startDTD(java.lang.String, java.lang.String, java.lang.String)

*/

public void startDTD(String name, String publicId, String systemId)

throws SAXException {

// TODO Auto-generated method stub

System.out.println("start DTD");

DefaultMutableTreeNode dtdReference = new DefaultMutableTreeNode("DTD for '" + name + "'");

if(publicId != null)

{

DefaultMutableTreeNode publicIDNode = new DefaultMutableTreeNode("Public ID: " + publicId + "'");

dtdReference.add(publicIDNode);

}

if(systemId != null)

{

DefaultMutableTreeNode systemIDNode = new DefaultMutableTreeNode("System ID: " + systemId + "'");

dtdReference.add(systemIDNode);

}

current.add(dtdReference);

}

/* (non-Javadoc)

* @see org.xml.sax.ext.LexicalHandler#startEntity(java.lang.String)

*/

public void startEntity(String name) throws SAXException {

// TODO Auto-generated method stub

DefaultMutableTreeNode entity = new DefaultMutableTreeNode("Entity: '" + name + "'");

current.add(entity);

current = entity;

}

public JTreeContentHandler(DefaultTreeModel treeModel,DefaultMutableTreeNode base)

{

this.treeModel = treeModel;

this.current = base;

this.namespaceMappings = new HashMap();

}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator)

*/

public void setDocumentLocator(Locator locator) {

// TODO Auto-generated method stub

this.locator = locator;



}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#startDocument()

*/

public void startDocument() throws SAXException {

// TODO Auto-generated method stub

System.out.println("start document");

}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#endDocument()

*/

public void endDocument() throws SAXException {

// TODO Auto-generated method stub

System.out.println("end document");

}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#startPrefixMapping(java.lang.String, java.lang.String)

*/

public void startPrefixMapping(String prefix, String uri) throws SAXException {

// TODO Auto-generated method stub

namespaceMappings.put(uri,prefix);

System.out.println("start PrefixMapping " + prefix);

}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#endPrefixMapping(java.lang.String)

*/

public void endPrefixMapping(String prefix) throws SAXException {

// TODO Auto-generated method stub

for(Iterator i = namespaceMappings.keySet().iterator();i.hasNext();)

{

String uri = (String) i.next();

String thisPrefix = (String)namespaceMappings.get(uri);

if(prefix.equals(thisPrefix)){

namespaceMappings.remove(uri);

break;

}

}

System.out.println("end PrefixMapping " + prefix);

}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes)

*/

public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {

// TODO Auto-generated method stub

DefaultMutableTreeNode element = new DefaultMutableTreeNode("Element: " + localName + " at line " + locator.getLineNumber());

current.add(element);

current = element;



if(uri.length() > 0)

{

String prefix = (String)namespaceMappings.get(uri);

if(prefix.equals("")){

prefix = "[None]";

}

DefaultMutableTreeNode namespace = new DefaultMutableTreeNode("Namespace: prefix = '" +

prefix + "',URI = '" + uri + "'");

current.add(namespace);

}



for(int i = 0;i
{

DefaultMutableTreeNode attribute = new DefaultMutableTreeNode("Attribute (name = '" +

atts.getLocalName(i) + "',value = '" + atts.getValue(i) + "')");

String attURI = atts.getURI(i);

if(attURI.length() > 0)

{

String attPrefix = (String)namespaceMappings.get(attURI);

if(attPrefix.equals("")){

attPrefix = "[None]";

}

DefaultMutableTreeNode attNamespace = new DefaultMutableTreeNode("Namespace: prefix = '" +

attPrefix + "',URI = '" + attURI + "'");

attribute.add(attNamespace);

}

current.add(attribute);

}

}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#endElement(java.lang.String, java.lang.String, java.lang.String)

*/

public void endElement(String uri, String localName, String qName) throws SAXException {

// TODO Auto-generated method stub

current = (DefaultMutableTreeNode)current.getParent();

}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#characters(char[], int, int)

*/

public void characters(char[] ch, int start, int length) throws SAXException {

// TODO Auto-generated method stub

String s = new String(ch,start,length);

DefaultMutableTreeNode data = new DefaultMutableTreeNode("Character Data: '" + s + "'");

current.add(data);

}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#ignorableWhitespace(char[], int, int)

*/

public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException {

// TODO Auto-generated method stub



}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#processingInstruction(java.lang.String, java.lang.String)

*/

public void processingInstruction(String target, String data) throws SAXException {

// TODO Auto-generated method stub

DefaultMutableTreeNode pi = new DefaultMutableTreeNode("PI (target = '"

+ target + "', data = '" + data + "')");

current.add(pi);

}



/* (non-Javadoc)

* @see org.xml.sax.ContentHandler#skippedEntity(java.lang.String)

*/

public void skippedEntity(String name) throws SAXException {

// TODO Auto-generated method stub

DefaultMutableTreeNode skipped = new DefaultMutableTreeNode("Skipped Entity: '" + name + "'");

current.add(skipped);

}

}



class JTreeErrorHandler implements ErrorHandler{



/* (non-Javadoc)

* @see org.xml.sax.ErrorHandler#warning(org.xml.sax.SAXParseException)

*/

public void warning(SAXParseException exception) throws SAXException {

// TODO Auto-generated method stub

System.out.println("**Parsing Warning**\n" +

" Line: " +

exception.getLineNumber() + "\n" +

" URI: " +

exception.getSystemId() + "\n" +

" Message:" +

exception.getMessage());

throw new SAXException("Warning encountered");

}



/* (non-Javadoc)

* @see org.xml.sax.ErrorHandler#error(org.xml.sax.SAXParseException)

*/

public void error(SAXParseException exception) throws SAXException {

// TODO Auto-generated method stub

System.out.println("**Parsing Error**\n" +

" Line: " +

exception.getLineNumber() + "\n" +

" URI: " +

exception.getSystemId() + "\n" +

" Message:" +

exception.getMessage());

throw new SAXException("Error encounted");

}



/* (non-Javadoc)

* @see org.xml.sax.ErrorHandler#fatalError(org.xml.sax.SAXParseException)

*/

public void fatalError(SAXParseException exception) throws SAXException {

// TODO Auto-generated method stub

System.out.println("**Parsing Fatal Error**\n" +

" Line: " +

exception.getLineNumber() + "\n" +

" URI: " +

exception.getSystemId() + "\n" +

" Message:" +

exception.getMessage());

throw new SAXException("Fatal Error encounted");

}



}

xml文件如下:你可以不用這個xml,用別的xml文件也可以









Java and XML







































































































































































































































&OReillyCopyright;


No comments:

Post a Comment