Android使用XML全攻略
入門
在本文中,您將學習如何構(gòu)建通過 Internet 使用 XML 的 Android 應用程序。Android 應用程序是使用 Java™ 編程語言編寫的,因此具備 Java 技術(shù)方面的經(jīng)驗是必需的。要進行 Android 開發(fā),您需要使用 android sdk。 本文中的所有代碼適用于任何版本的 Android SDK,但 SDK 1.5_pre 是用于開發(fā)代碼的。您可以使用 SDK 和一個文本編輯器來開發(fā) Android 應用程序,但使用Android Developer Tools (ADT)(一款 Eclipse 插件)會更加簡單。在本文中,我們使用 0.9 版本的 ADT 和 Eclipse 3.4.2, Java 版本。有關(guān)所有這些工具的鏈接,請參見 參考資料。
Android上的XML
Android 平臺是一個開源移動開發(fā)平臺。它允許您訪問各種移動設備的所有方面,這些移動設備從低級圖形設備到手機攝像頭上的硬件不一而足。由于 Android 可以實現(xiàn)這么豐富的功能,因此您可能想知道為何還要為 XML 傷腦筋呢。并不是因為使用 XML 是多么地有趣;而是因為它能提供一些特殊的支持。XML經(jīng)常用作 Internet上的一種數(shù)據(jù)格式。如果您希望通過 Internet 訪問數(shù)據(jù),則數(shù)據(jù)很有可能是 XML 格式。如果您希望發(fā)送數(shù)據(jù)給 Web 服務,那么您可能也需要發(fā)送 XML。簡而言之,如果您的Android應用程序?qū)⒗?Internet,那么您可能需要使用 XML。幸運的是,您可以采用多種方法在Android上使用 XML。
XML 解析器常用縮略語
- API:應用程序編程接口(Application programming interface)
- RSS:Really Simple Syndication
- SDK:軟件開發(fā)包(Software Developers Kit)
- UI:用戶界面(User interface)
- URL:通用資源定位符(Universal Resource Locator)
- XML:可擴展標記語言(Extensible Markup Language)
Android 平臺最大的一個優(yōu)勢在于它利用了 Java 編程語言。Android SDK 并未向您的標準 Java Runtime Environment (JRE) 提供一切可用功能,但它支持其中很大一部分功能。Java 平臺支持通過許多不同的方式來使用 XML,并且大多數(shù)與 XML 相關(guān)的 Java API 在 Android 上得到了完全支持。舉例來說,Java 的 Simple API for XML (SAX) 和 Document Object Model (DOM) 在 Android 上都是可用的。這些 API 多年以來一直都是 Java 技術(shù)的一部分。較新的 Streaming API for XML (StAX) 在 Android 中并不可用。但是, Android 提供了一個功能相當?shù)膸?。最后,Java XML Binding API 在 Android 中也不可用。這個 API 已確定可以在 Android 中實現(xiàn)。但是,它更傾向于是一個重量級的 API,需要使用許多不同類的實例來表示 XML 文檔。因此,這對于受限的環(huán)境,比如說 Android 針對的手持設備,不太理想。在后續(xù)小節(jié)中,我們將以 Internet 上的一個簡單的 XML 源為例,來看看如何在 Android 應用程序中使用上述各種 API 來解析它。首先,我們來看看這個簡單應用程序的主要部分,它將通過 Internet 來使用 XML。
Android 新聞閱讀器
應用程序?qū)臒衢T Android 開發(fā)人員站點 Androidster 獲取一個 RSS 提要,并將它解析為一組簡單的 Java 對象,您可以使用這些對象構(gòu)建一個 Android ListView(參見下載部分獲取源代碼)。這是一種典型的多態(tài)行為 — 提供相同行為的不同實現(xiàn)(不同的 XML 解析算法)。清單 1 展示了如何在 Java 代碼中使用一個接口建立這一模型。
清單 1. XML 提要解析器接口[size=0.76em]
- package org.developerworks.android;
- import java.util.List;
- public interface FeedParser {
- List<Message> parse();
- }
在清單2中,Message 類是一個典型的 Plain Old Java Object (POJO),它表示一種數(shù)據(jù)結(jié)構(gòu)。
清單 2. Message POJO
- public class Message implements Comparable<Message>{
- static SimpleDateFormat FORMATTER =
- new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z");
- private String title;
- private URL link;
- private String description;
- private Date date;
- // getters and setters omitted for brevity
- public void setLink(String link) {
- try {
- this.link = new URL(link);
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
- public String getDate() {
- return FORMATTER.format(this.date);
- }
- public void setDate(String date) {
- // pad the date if necessary
- while (!date.endsWith("00")){
- date += "0";
- }
- try {
- this.date = FORMATTER.parse(date.trim());
- } catch (ParseException e) {
- throw new RuntimeException(e);
- }
- }
- @Override
- public String toString() {
- // omitted for brevity
- }
- @Override
- public int hashCode() {
- // omitted for brevity
- }
- @Override
- public boolean equals(Object obj) {
- // omitted for brevity
- }
- // sort by date
- public int compareTo(Message another) {
- if (another == null) return 1;
- // sort descending, most recent first
- return another.date.compareTo(date);
- }
- }
清單 2 中的消息基本上是相當直觀的。通過允許日期和鏈接作為簡單的對象被訪問,同時將它們表示為較強類型的對象(java.util.Date 和 java.net.URL),它隱藏了一些內(nèi)部狀態(tài)。它是一個典型的 Value Object,因此它基于其內(nèi)部狀態(tài)實現(xiàn)了equals() 和 hashCode()。它還實現(xiàn)了 Comparable 接口,因此您可以使用它進行排序(按日期)。在實踐中,提要中的數(shù)據(jù)始終是有序的,因為沒有必要再進行排序。
每個解析器實現(xiàn)都需要提供一個URL給Androidster提要,并使用它打開一個到Androidster站點的HTTP連接。這一常見行為自然是在 Java 代碼中建模,我們使用了一個抽象基類,如清單3所示。
清單 3. 基本提要解析器類
- public abstract class BaseFeedParser implements FeedParser {
- // names of the XML tags
- static final String PUB_DATE = "pubDate";
- static final String DESCRIPTION = "description";
- static final String LINK = "link";
- static final String TITLE = "title";
- static final String ITEM = "item";
- final URL feedUrl;
- protected BaseFeedParser(String feedUrl){
- try {
- this.feedUrl = new URL(feedUrl);
- } catch (MalformedURLException e) {
- throw new RuntimeException(e);
- }
- }
- protected InputStream getInputStream() {
- try {
- return feedUrl.openConnection().getInputStream();
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
- }
- }
基類存儲 feedUrl 并使用它打開了一個 java.io.InputStream。如果出現(xiàn)任何差錯,它會拋出一個 RuntimeException,造成應用程序出現(xiàn)故障。基類還為標記的名稱定義了一些簡單的常量。清單 4 顯示了提要中的一些示例內(nèi)容,以便于您理解這些標記的重要性。
清單 4.示例XML提要
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- generator="FeedCreator 1.7.2" -->
- <rss version="2.0">
- <channel>
- <title>android_news</title>
- <description>android_news</description>
- <link><a href="\"http://www.androidster.com/android_news.php</link>\"" target="\"_blank\"">http://www.androidster.com/android_news.php</link></a>
- <lastBuildDate>Sun, 19 Apr 2009 19:43:45 +0100</lastBuildDate>
- <generator>FeedCreator 1.7.2</generator>
- <item>
- <title>Samsung S8000 to Run Android, Play DivX, Take Over the
- World</title>
- <link><a href="\"http://www.androidster.com/android_news/samsung-s8000-to-run-android-\"" target="\"_blank\"">http://www.androidster.com/andro ... 000-to-run-android-</a>
- play-divx-take-over-the-world</link>
- <description>More details have emerged on the first Samsung handset
- to run Android. A yet-to-be announced phone called the S8000 is being
- reported ...</description>
- <pubDate>Thu, 16 Apr 2009 07:18:51 +0100</pubDate>
- </item>
- <item>
- <title>Android Cupcake Update on the Horizon</title>
- <link><a href="\"http://www.androidster.com/android_news/android-cupcake-update-\"" target="\"_blank\"">http://www.androidster.com/android_news/android-cupcake-update-</a>
- on-the-horizon</link>
- <description>After months of discovery and hearsay, the Android
- build that we have all been waiting for is about to finally make it
- out ...</description>
- <pubDate>Tue, 14 Apr 2009 04:13:21 +0100</pubDate>
- </item>
- </channel>
- </rss>
如清單4中的示例所示,一個ITEM對應于一個Message實例。項目的子節(jié)點(TITLE、LINK 等)對應于 Message 實例的屬性?,F(xiàn)在,您已經(jīng)對提要有了一定的認識,并且已經(jīng)創(chuàng)建了所有常用部分,接下來看看如何使用 Android 上可用的各種技術(shù)來解析這個提要。您將從 SAX 開始。
使用 SAX
在Java環(huán)境中,當您需要一個速度快的解析器并且希望最大限度減少應用程序的內(nèi)存占用時,通??梢允褂?SAX API。這非常適用于運行 Android 的移動設備。您可以在 Java 環(huán)境中照原樣使用 SAX API,在 Android 上運行它不需要做任何修改。清單 5 顯示了FeedParser 接口的一個 SAX 實現(xiàn)。
清單 5. SAX 實現(xiàn)
- public class SaxFeedParser extends BaseFeedParser {
- protected SaxFeedParser(String feedUrl){
- super(feedUrl);
- }
- public List<Message> parse() {
- SAXParserFactory factory = SAXParserFactory.newInstance();
- try {
- SAXParser parser = factory.newSAXParser();
- RssHandler handler = new RssHandler();
- parser.parse(this.getInputStream(), handler);
- return handler.getMessages();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
- }
如果您以前使用過 SAX,那么這對您肯定非常熟悉。與任何 SAX 實現(xiàn)相同,大多數(shù)細節(jié)都在 SAX 處理程序中。在分解 XML 文檔時,處理程序從 SAX 解析器接收事件。在本例中,您創(chuàng)建了一個新的名稱為 RssHandler 的類,并將它注冊為解析器的處理程序,如 清單 6 所示。
清單 6. SAX 處理程序
- import static org.developerworks.android.BaseFeedParser.*;
- public class RssHandler extends DefaultHandler{
- private List<Message> messages;
- private Message currentMessage;
- private StringBuilder builder;
- public List<Message> getMessages(){
- return this.messages;
- }
- @Override
- public void characters(char[] ch, int start, int length)
- throws SAXException {
- super.characters(ch, start, length);
- builder.append(ch, start, length);
- }
- @Override
- public void endElement(String uri, String localName, String name)
- throws SAXException {
- super.endElement(uri, localName, name);
- if (this.currentMessage != null){
- if (localName.equalsIgnoreCase(TITLE)){
- currentMessage.setTitle(builder.toString());
- } else if (localName.equalsIgnoreCase(LINK)){
- currentMessage.setLink(builder.toString());
- } else if (localName.equalsIgnoreCase(DESCRIPTION)){
- currentMessage.setDescription(builder.toString());
- } else if (localName.equalsIgnoreCase(PUB_DATE)){
- currentMessage.setDate(builder.toString());
- } else if (localName.equalsIgnoreCase(ITEM)){
- messages.add(currentMessage);
- }
- builder.setLength(0);
- }
- }
- @Override
- public void startDocument() throws SAXException {
- super.startDocument();
- messages = new ArrayList<Message>();
- builder = new StringBuilder();
- }
- @Override
- public void startElement(String uri, String localName, String name,
- Attributes attributes) throws SAXException {
- super.startElement(uri, localName, name, attributes);
- if (localName.equalsIgnoreCase(ITEM)){
- this.currentMessage = new Message();
- }
- }
- }
RssHandler 類擴展了 org.xml.sax.helpers.DefaultHandler 類。該類為 SAX 解析器生成的事件所對應的所有方法都提供了一個默認的非操作實現(xiàn)。這允許子類根據(jù)需要僅覆蓋一些方法。RssHandler 提供了一個額外的 API,即 getMessages。它返回處理程序在從 SAX 解析器接收事件時所收集的 Message 對象列表。它有另外兩個內(nèi)部變量,currentMessage 針對被解析的 Message 實例,以及名稱為 builder 的 StringBuilder 變量,用于存儲文本節(jié)點中的字符數(shù)據(jù)。解析器將相應事件發(fā)送給處理程序時會調(diào)用 startDocument 方法,這兩個變量的初始化操作就是在此時完成。
查看清單6中的startElement方法。在XML文檔中每次遇到開始標記時都會調(diào)用它。您只關(guān)心該標記何時為ITEM標記。對于這種情況,您將創(chuàng)建一個新的Message?,F(xiàn)在來看characters方法。遇到文本節(jié)點中的字符數(shù)據(jù)時便會調(diào)用此方法。數(shù)據(jù)只是被添加到builder變量中。最后,我們來看endElement方法。遇到結(jié)束標記時會調(diào)用此方法。對于與某Message屬性相對應的標記,如TITLE和LINK,則使用builder變量中的數(shù)據(jù)在currentMessage上設置適當?shù)膶傩浴H绻Y(jié)束標記是一個ITEM,則currentMessage將被添加到Messages列表中。所有這些都是非常典型的SAX解析;此處的一切都不是Android所特有的。因此,如果您知道如何編寫Java SAX解析器,則應該知道如何編寫Android SAX解析器。但是,Android SDK確實在SAX上添加了一些便捷的特性。
別走開,精彩下頁繼續(xù)
#p#
更加簡單的 SAX 解析
Android SDK 提供了一個名稱為android.util.Xml的實用類。清單 7 展示了如何使用這個相同的實用類來設置一個 SAX 解析器。
清單 7. Android SAX 解析器
- public class AndroidSaxFeedParser extends BaseFeedParser {
- public AndroidSaxFeedParser(String feedUrl) {
- super(feedUrl);
- }
- public List<Message> parse() {
- RssHandler handler = new RssHandler();
- try {
- Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, handler);
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return handler.getMessages();
- }
- }
注意,這個類仍然使用了一個標準的 SAX 處理程序,因此您僅僅重用了 清單 7 中所示的 RssHandler。能夠重用 SAX 處理程序是非常不錯的,但其代碼稍微有些復雜。您可以想像,如果需要解析一個更加復雜的 XML 文檔,則處理程序可能會帶來各種各樣的 bug。舉例來說,回頭看看 清單 6 中的 endElement 方法。注意,在嘗試設置屬性之前,它檢查了 currentMessage 是否為 null?,F(xiàn)在,再回頭看看 清單 4 中的示例 XML。 注意,ITEM 標記外部有一些 TITLE 和 LINK 標記。這就是使用 null 檢查的原因。否則,每一個 TITLE標記 會導致一個 NullPointerException。Android 提供了自己獨有的 SAX API(參見 清單 8),它排除了您編寫自己的 SAX 處理程序的需要。
清單 8. 經(jīng)過簡化的 Android SAX 解析器
- public class AndroidSaxFeedParser extends BaseFeedParser {
- public AndroidSaxFeedParser(String feedUrl) {
- super(feedUrl);
- }
- public List<Message> parse() {
- final Message currentMessage = new Message();
- RootElement root = new RootElement("rss");
- final List<Message> messages = new ArrayList<Message>();
- Element channel = root.getChild("channel");
- Element item = channel.getChild(ITEM);
- item.setEndElementListener(new EndElementListener(){
- public void end() {
- messages.add(currentMessage.copy());
- }
- });
- item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener(){
- public void end(String body) {
- currentMessage.setTitle(body);
- }
- });
- item.getChild(LINK).setEndTextElementListener(new EndTextElementListener(){
- public void end(String body) {
- currentMessage.setLink(body);
- }
- });
- item.getChild(DESCRIPTION).setEndTextElementListener(new
- EndTextElementListener(){
- public void end(String body) {
- currentMessage.setDescription(body);
- }
- });
- item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener(){
- public void end(String body) {
- currentMessage.setDate(body);
- }
- });
- try {
- Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8,
- root.getContentHandler());
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return messages;
- }
- }
新的SAX 解析代碼并未使用 SAX 處理程序,而是使用了 SDK 中的 android.sax 包中的類。這些類允許您構(gòu)建 XML 文檔的結(jié)構(gòu),并根據(jù)需要添加事件監(jiān)聽程序。在以上代碼中,您聲明文檔將有一個 rss 根元素,并且它有一個 channel 子元素。然后,您聲明channel 將有一個 ITEM 子元素,并且開始添加監(jiān)聽程序。對于每個監(jiān)聽程序,您都使用了一個實現(xiàn)了特定接口(EndElementListner或 EndTextElementListener)的匿名內(nèi)部類。注意,您不需要跟蹤字符數(shù)據(jù)。不僅僅因為這樣會更加簡單,更重要的是更加高效。最后,在調(diào) 用 Xml.parse 實用方法時,您將傳遞一個通過根元素生成的處理程序。
清單 8 中的所有代碼都是可選的。如果您習慣 Java 環(huán)境中的標準 SAX 解析代碼,那么您可以堅持使用它。如果您希望嘗試 Android SDK 所提供的便捷的包裝器,那么也可以使用它。如果您完全不希望使用 SAX 會怎樣呢?可以使用一些備選方案。其中的首選方法就是 DOM。
使用 DOM
Android 完全支持 DOM 解析,就像在桌面機器或服務器上使用 Java 代碼運行它一樣。清單 9 顯示了一個基于 DOM 的解析器接口實現(xiàn)。
清單 9. 基于 DOM 的提要解析器實現(xiàn)
- public class DomFeedParser extends BaseFeedParser {
- protected DomFeedParser(String feedUrl) {
- super(feedUrl);
- }
- public List<Message> parse() {
- DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
- List<Message> messages = new ArrayList<Message>();
- try {
- DocumentBuilder builder = factory.newDocumentBuilder();
- Document dom = builder.parse(this.getInputStream());
- Element root = dom.getDocumentElement();
- NodeList items = root.getElementsByTagName(ITEM);
- for (int i=0;i<items.getLength();i++){
- Message message = new Message();
- Node item = items.item(i);
- NodeList properties = item.getChildNodes();
- for (int j=0;j<properties.getLength();j++){
- Node property = properties.item(j);
- String name = property.getNodeName();
- if (name.equalsIgnoreCase(TITLE)){
- message.setTitle(property.getFirstChild().getNodeValue());
- } else if (name.equalsIgnoreCase(LINK)){
- message.setLink(property.getFirstChild().getNodeValue());
- } else if (name.equalsIgnoreCase(DESCRIPTION)){
- StringBuilder text = new StringBuilder();
- NodeList chars = property.getChildNodes();
- for (int k=0;k<chars.getLength();k++){
- text.append(chars.item(k).getNodeValue());
- }
- message.setDescription(text.toString());
- } else if (name.equalsIgnoreCase(PUB_DATE)){
- message.setDate(property.getFirstChild().getNodeValue());
- }
- }
- messages.add(message);
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return messages;
- }
- }
與第一個 SAX 示例類似,以上代碼完全沒有特定于 Android 的地方。DOM 解析器將所有 XML 文檔讀取到內(nèi)存中,然后允許您使用 DOM API 遍歷 XML 樹、檢索所需的數(shù)據(jù)。這是非常直觀的代碼,并且,在某些方面比基于 SAX 的實現(xiàn)更加簡單。但是,DOM 通常更加占用內(nèi)存,因為一切內(nèi)容都會先讀取到內(nèi)存中。這對于運行 Android 的移動設備來說是一個問題,但是當 XML 文檔始終保持很小的大小時是可行的。這可能意味著,Android 的開發(fā)人員會認為 SAX 解析在 Android 應用程序上更加常見,因此為它提供了額外的實用工具。Android 還提供了另一種類型的 XML 解析器,它就是 pull 解析器。
XML pull 解析器
如前所述,Android 并未提供對 Java StAX API 的支持。但是,Android 確實附帶了一個 pull 解析器,其工作方式類似于 StAX。它允許您的應用程序代碼從解析器中獲取事件,這與 SAX 解析器自動將事件推入處理程序相反。清單 10 顯示了提要解析接口的一個 pull 解析器實現(xiàn)。
清單 10. 基于 Pull 解析器的實現(xiàn)
- public class XmlPullFeedParser extends BaseFeedParser {
- public XmlPullFeedParser(String feedUrl) {
- super(feedUrl);
- }
- public List<Message> parse() {
- List<Message> messages = null;
- XmlPullParser parser = Xml.newPullParser();
- try {
- // auto-detect the encoding from the stream
- parser.setInput(this.getInputStream(), null);
- int eventType = parser.getEventType();
- Message currentMessage = null;
- boolean done = false;
- while (eventType != XmlPullParser.END_DOCUMENT && !done){
- String name = null;
- switch (eventType){
- case XmlPullParser.START_DOCUMENT:
- messages = new ArrayList<Message>();
- break;
- case XmlPullParser.START_TAG:
- name = parser.getName();
- if (name.equalsIgnoreCase(ITEM)){
- currentMessage = new Message();
- } else if (currentMessage != null){
- if (name.equalsIgnoreCase(LINK)){
- currentMessage.setLink(parser.nextText());
- } else if (name.equalsIgnoreCase(DESCRIPTION)){
- currentMessage.setDescription(parser.nextText());
- } else if (name.equalsIgnoreCase(PUB_DATE)){
- currentMessage.setDate(parser.nextText());
- } else if (name.equalsIgnoreCase(TITLE)){
- currentMessage.setTitle(parser.nextText());
- }
- }
- break;
- case XmlPullParser.END_TAG:
- name = parser.getName();
- if (name.equalsIgnoreCase(ITEM) &&
- currentMessage != null){
- messages.add(currentMessage);
- } else if (name.equalsIgnoreCase(CHANNEL)){
- done = true;
- }
- break;
- }
- eventType = parser.next();
- }
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- return messages;
- }
- }
pull 解析器的運行方式與 SAX 解析器相似。它提供了類似的事件(開始元素和結(jié)束元素),但您需要使用 (parser.next() 提取它們。事件將作為數(shù)值代碼被發(fā)送,因此您可以使用一個簡單 case-switch。注意,解析并未像 SAX 解析那樣監(jiān)聽元素的結(jié)束,而是在開始處完成了大部分處理。在 清單 10 的代碼中,當某個元素開始時,您可以調(diào)用 parser.nextText() 從 XML 文檔中提取所有字符數(shù)據(jù)。還需注意,您設置了一個標記(布爾變量 done)來確定何時到達感興趣內(nèi)容的結(jié)束部分。這允許您提早停止讀取 XML 文檔,因為您知道代碼將不會關(guān)心文檔的其余部分。這有時非常實用,特別是當您只需要訪問一小部分 XML 文檔時。通過盡快停止解析,您可以極大地減少解析時間。這種優(yōu)化對于連接速度較慢的移動設備尤為重要。pull 解析器可以提供一些性能優(yōu)勢以及易用性。它還可以用于編寫 XML。
創(chuàng)建 XML
目前為止,我一直專注于通過 Internet 解析 XML。但是,有時您的應用程序可能需要將 XML 發(fā)送到遠程服務器。顯然,您可以只使用一個 StringBuilder 來創(chuàng)建 XML 字符串。另一種備選方法來自 清單 11 中的 Pull 解析器。
清單 11. 使用 pull 解析器編寫 XML
- private String writeXml(List<Message> messages){
- XmlSerializer serializer = Xml.newSerializer();
- StringWriter writer = new StringWriter();
- try {
- serializer.setOutput(writer);
- serializer.startDocument("UTF-8", true);
- serializer.startTag("", "messages");
- serializer.attribute("", "number", String.valueOf(messages.size()));
- for (Message msg: messages){
- serializer.startTag("", "message");
- serializer.attribute("", "date", msg.getDate());
- serializer.startTag("", "title");
- serializer.text(msg.getTitle());
- serializer.endTag("", "title");
- serializer.startTag("", "url");
- serializer.text(msg.getLink().toExternalForm());
- serializer.endTag("", "url");
- serializer.startTag("", "body");
- serializer.text(msg.getDescription());
- serializer.endTag("", "body");
- serializer.endTag("", "message");
- }
- serializer.endTag("", "messages");
- serializer.endDocument();
- return writer.toString();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
XmlSerializer 類是 前一部分 所使用的 XmlPullParser 包的一部分。它沒有提取事件,而是將它們推出到數(shù)據(jù)流或編寫程序中。在本例中,它僅僅將事件推送到了一個 java.io.StringWriter 實例中。它提供了一個直觀的 API,通過各種方法開始和結(jié)束文檔、處理元素以及添加文本或?qū)傩浴_@是StringBuilder的一種出色的替換方案,因為它可以更加輕松地確保您的 XML 具有良好結(jié)構(gòu)。
結(jié)束語
您希望為Android設備構(gòu)建何種類型的應用程序?無論如何,如果它需要通過 Internet 使用數(shù)據(jù),那么都可能需要使用XML。在本文中,您看到 Android 提供了大量用于處理XML的工具。您可以選擇其中之一作為自己的工具,或者您可以根據(jù)用例來進行選擇。大多數(shù)時間,使用SAX是比較安全的,并且Android提供了一種傳統(tǒng)的SAX 使用方法,以及一個便捷的SAX包裝器。如果您的文檔比較小,那么DOM可能是一種比較簡單的方法。如果您的文檔比較大,但您只需要文檔的一部分,則XML Pull解析器可能是更為有效的方法。最后,對于編寫XML,Pull解析器包也提供了一種便捷的方法。因此,無論您的XML需求如何,Android都能在一定程度上滿足它們。