[Android] 要學會的關鍵技術—XML的讀取(1)

device-2012-03-23-142254  

系列文章:

[Android] 要學會的關鍵技術—XML的讀取(1) 

[Android] 要學會的關鍵技術—XML的讀取(2) 

[Android] 要學會的關鍵技術—XML的讀取(3) 

 

在Android開發之中,很重要的就是跟網路連線

今天談論XML的資料格式的傳遞

在Android的XML解析上有二種方式:

  1. DOM (Document Object Model),他會把整份XML檔案載入,然後成為一個樹狀物件

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

很多效能測試上,SAX比DOM更有效率
這次的範例也是用SAX做的

 

這要配合XML格式來看

XML無所不在,最常用的RSS、你的Android的版面檔…

舉個RSS的例子好了,RSS也是用XML去做的

例如 Yahoo!奇摩 旅遊新聞

http://tw.news.yahoo.com/rss/travel

你用Chrome打開可能會長這樣

2013-01-06 22 32 32   

那是Chrome已經幫你整理過了,所有的元素(element)旁都有個箭頭可以縮放

這樣還是看不懂,沒關係,我來幫你整理一下
一個旅遊新聞RSS大概長這樣
(以下內容有部份元素省略)

 

<?xml version=“1.0” encoding=“utf-8”?>

<rss version=“2.0” >

    <channel>

        <title>旅遊新聞頭條新聞 – Yahoo!奇摩新聞</title>

        <link>http://tw.news.yahoo.com/travel/</link>

        <description>(…)</description>

        <language>zh-Hant-TW</language>

        <pubDate>Sun, 06 Jan 2013 05:30:00 +0800</pubDate>

        <ttl>5</ttl>

        <item>

            <title>冬日泡湯香港客愛北投</title>

                <link>http://tw.news.yahoo.com/(…)-024412185.html</link>

            <pubDate>Sun, 06 Jan 2013 10:44:12 +0800</pubDate>

                <description>(…)</description>

        </item>

    </channel>

</rss>

 

就如從剛剛所提到,RSS是照著XML的格式規範走的
開頭第一行就有XML的宣告,之後的內容就跟HTML感覺很像啦

這文件包含了RSS的channel(頻道)、頻道的名字、連結、頻道介紹、語言別、更新日期…等

item裡面的東西比較重要,代表一個RSS項目(Maybe是一篇文章、新聞),它的標題、連結、時間、簡介…等

 


再看一個例子好了,例如小弟部落格的RSS

http://feed.pixnet.net/blog/posts/rss/j796160836

內容節錄在這:

<?xml version=“1.0” encoding=“UTF-8”?>

<rss xmlns:content=“http://purl.org/rss/1.0/modules/content/” xmlns:atom=“http://www.w3.org/2005/Atom” version=“2.0”>

  <channel>

    <title><![CDATA[清新下午茶 :: 痞客邦 PIXNET ::]]></title>

    <link>http://j796160836.pixnet.net/blog</link>

    <description><![CDATA[夏天的午後,來杯下午茶,分享你我的心。]]></description>

    <pubDate>Thu, 15 Nov 2012 08:11:58 +0000</pubDate>

    <copyright>Copyright 2003-2013 Johnny ,Pixnet Digital Media Coporation. All rights reserved.</copyright>

    <generator>PIXNET Media Digital Coporation</generator>

    <language>zh</language>

    <docs>http://blogs.law.harvard.edu/tech/rss</docs>

    <atom:link rel=“hub” href=“http://pubsubhubbub.appspot.com:80”/>   

    <item>

      <title><![CDATA[[Android] 使用HTTPPOST方式和網頁表單溝通 (加上資料庫、執行緒)]]></title>

      <link>http://j796160836.pixnet.net/blog/post/30577968</link>

      <guid>http://j796160836.pixnet.net/blog/post/30577968</guid>

      <description><![CDATA[  (…) ]]></description>

      <content:encoded><![CDATA[  (…]]></content:encoded>

      <pubDate>Thu, 05 Apr 2012 16:19:35 +0000</pubDate>

      <category>Android</category>

      <comments>http://j796160836.pixnet.net/blog/post/30577968#comments</comments>

    </item>

  </channel>

</rss>

 

雖然內容比較多,但很多只要看重點就可以了

從剛剛的例子知道

要找這個頻道的名稱要找

rss -> channel -> title

要找一個項目(文章)的標題,就

rss -> channel -> item -> title

(其實這只是方便理解,表示路徑有正規的寫法,叫XPath …有興趣可以google一下)

這裡多的xmlns:contentxmlns:atomatom:link

都只是宣告不重要

但這裡多了個<content:encoded></content:encoded>標籤
它跟<description></description>的差別

只在於content:encoded是用HTML標籤格式化過的

description是純文字

 

眼尖的你應該有發現<![CDATA[   ]]>符號

它是告訴剖析器(parser),用這符號括起來的內容,沒有做任何的跳脫處理

例如:< 符號要寫成 &lt; 等等

請視為整段文字做處理

 

因為它是RSS,所以有格式規定

如果是你自己寫XML文件的話,格式都可以自己訂

 


 

剛剛提到了SAX採用事件的方式處理,所以我簡單列出以下的一些事件callback函數

 

文件類:

     * XML文件開始解析時呼叫此method

    public void startDocument() throws SAXException

     * XML文件結束時呼叫此method

    public void endDocument() throws SAXException

節點類:

     * 解析到Element的開頭時呼叫此method

    public void startElement(String namespaceURI, String localName,

            String qName, Attributes atts) throws SAXException 

     * 解析到Element的結尾時呼叫此method

    public void endElement(String namespaceURI, String localName, String qName)

            throws SAXException

節點內容:

     * 取得Element的開頭結尾中間夾的字串

    public void characters(String fetchStr)

 

到時候配上程式碼就大致就會知道了

它到時候要接一個DefaultHandler實做以上方法

 

我的話通常會把RSS資料擺到自己設計的物件(Object)裡面

到時候直接存檔,用ArrayList配合ListView做資料展示都很方便

 

像在startDocument()的時候通常會做一些變數的宣告(ArrayList)

SAX的問題就是:我只知道讀到節點了,但我不知道讀到哪一個節點(多深)

很多書上都是寫用元素的名稱做判斷

但我提出一個更方便更精準的做法

 

我把讀取的歷程用Stack(堆疊)記錄下來

意指在 startElement() 時把qName給push進去

in_node.push(qName); 

到了 endElement() 時把它pop掉

in_node.pop();

這個很簡單的動作我就可以知道我的歷程了

 

 

這篇先講概念,後面的程式碼才會看得比較有重點

[Android] 要學會的關鍵技術—XML的讀取(2) 

[Android] 要學會的關鍵技術—XML的讀取(3)  

 


 

參考資料

 

RSS的介紹

http://zh.wikipedia.org/zh-tw/RSS

http://tw.info.yahoo.com/rss/rookie.html

SAX的剖析方式

http://zh.wikipedia.org/zh-tw/SAX

CDDATA的說明

http://ianjung1974.blogspot.tw/2008/04/cdata-xml.html

Android 解析 XML

http://www.dotblogs.com.tw/nethawk/archive/2011/05/02/24047.aspx

 

 

在〈[Android] 要學會的關鍵技術—XML的讀取(1)〉中有 1 則留言

留言功能已關閉。