精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Android使用XML全攻略

移動開發 Android
Android 是針對移動設備的一種新興的開源操作系統和 SDK。借助它,您可以創建功能強大的移動應用程序。當您的應用程序可以訪問 Web 服務時,其吸引力會大大增加,這意味著您需要使用 Web 語言:XML。在本文中,您將了解在 Android 上使用 XML 的不同方法,以及如何使用它們構建自己的 Android 應用程序。

入門

在本文中,您將學習如何構建通過 Internet 使用 XML 的 Android 應用程序。Android 應用程序是使用 Java™ 編程語言編寫的,因此具備 Java 技術方面的經驗是必需的。要進行 Android 開發,您需要使用 android sdk。 本文中的所有代碼適用于任何版本的 Android SDK,但 SDK 1.5_pre 是用于開發代碼的。您可以使用 SDK 和一個文本編輯器來開發 Android 應用程序,但使用Android Developer Tools (ADT)(一款 Eclipse 插件)會更加簡單。在本文中,我們使用 0.9 版本的 ADT 和 Eclipse 3.4.2, Java 版本。有關所有這些工具的鏈接,請參見 參考資料。

Android上的XML

Android 平臺是一個開源移動開發平臺。它允許您訪問各種移動設備的所有方面,這些移動設備從低級圖形設備到手機攝像頭上的硬件不一而足。由于 Android 可以實現這么豐富的功能,因此您可能想知道為何還要為 XML 傷腦筋呢。并不是因為使用 XML 是多么地有趣;而是因為它能提供一些特殊的支持。XML經常用作 Internet上的一種數據格式。如果您希望通過 Internet 訪問數據,則數據很有可能是 XML 格式。如果您希望發送數據給 Web 服務,那么您可能也需要發送 XML。簡而言之,如果您的Android應用程序將利用 Internet,那么您可能需要使用 XML。幸運的是,您可以采用多種方法在Android上使用 XML。

XML 解析器常用縮略語

  • API:應用程序編程接口(Application programming interface)
  • RSS:Really Simple Syndication
  • SDK:軟件開發包(Software Developers Kit)
  • UI:用戶界面(User interface)
  • URL:通用資源定位符(Universal Resource Locator)
  • XML:可擴展標記語言(Extensible Markup Language)

Android 平臺最大的一個優勢在于它利用了 Java 編程語言。Android SDK 并未向您的標準 Java Runtime Environment (JRE) 提供一切可用功能,但它支持其中很大一部分功能。Java 平臺支持通過許多不同的方式來使用 XML,并且大多數與 XML 相關的 Java API 在 Android 上得到了完全支持。舉例來說,Java 的 Simple API for XML (SAX) 和 Document Object Model (DOM) 在 Android 上都是可用的。這些 API 多年以來一直都是 Java 技術的一部分。較新的 Streaming API for XML (StAX) 在 Android 中并不可用。但是, Android 提供了一個功能相當的庫。最后,Java XML Binding API 在 Android 中也不可用。這個 API 已確定可以在 Android 中實現。但是,它更傾向于是一個重量級的 API,需要使用許多不同類的實例來表示 XML 文檔。因此,這對于受限的環境,比如說 Android 針對的手持設備,不太理想。在后續小節中,我們將以 Internet 上的一個簡單的 XML 源為例,來看看如何在 Android 應用程序中使用上述各種 API 來解析它。首先,我們來看看這個簡單應用程序的主要部分,它將通過 Internet 來使用 XML。

Android 新聞閱讀器

應用程序將從熱門 Android 開發人員站點 Androidster 獲取一個 RSS 提要,并將它解析為一組簡單的 Java 對象,您可以使用這些對象構建一個 Android ListView(參見下載部分獲取源代碼)。這是一種典型的多態行為 — 提供相同行為的不同實現(不同的 XML 解析算法)。清單 1 展示了如何在 Java 代碼中使用一個接口建立這一模型。

清單 1. XML 提要解析器接口[size=0.76em]

  1. package org.developerworks.android; 
  2. import java.util.List; 
  3. public interface FeedParser { 
  4. List<Message> parse(); 

在清單2中,Message 類是一個典型的 Plain Old Java Object (POJO),它表示一種數據結構。
清單 2. Message POJO

  1. public class Message implements Comparable<Message>{ 
  2. static SimpleDateFormat FORMATTER = 
  3. new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z"); 
  4. private String title; 
  5. private URL link; 
  6. private String description; 
  7. private Date date; 
  8. // getters and setters omitted for brevity 
  9. public void setLink(String link) { 
  10. try { 
  11. this.link = new URL(link); 
  12. catch (MalformedURLException e) { 
  13. throw new RuntimeException(e); 
  14. public String getDate() { 
  15. return FORMATTER.format(this.date); 
  16. public void setDate(String date) { 
  17. // pad the date if necessary 
  18. while (!date.endsWith("00")){ 
  19. date += "0"
  20. try { 
  21. this.date = FORMATTER.parse(date.trim()); 
  22. catch (ParseException e) { 
  23. throw new RuntimeException(e); 
  24. @Override 
  25. public String toString() { 
  26. // omitted for brevity 
  27. @Override 
  28. public int hashCode() { 
  29. // omitted for brevity 
  30. @Override 
  31. public boolean equals(Object obj) { 
  32. // omitted for brevity 
  33. // sort by date 
  34. public int compareTo(Message another) { 
  35. if (another == nullreturn 1
  36. // sort descending, most recent first 
  37. return another.date.compareTo(date); 

清單 2 中的消息基本上是相當直觀的。通過允許日期和鏈接作為簡單的對象被訪問,同時將它們表示為較強類型的對象(java.util.Datejava.net.URL),它隱藏了一些內部狀態。它是一個典型的 Value Object,因此它基于其內部狀態實現了equals()hashCode()。它還實現了 Comparable 接口,因此您可以使用它進行排序(按日期)。在實踐中,提要中的數據始終是有序的,因為沒有必要再進行排序。

每個解析器實現都需要提供一個URL給Androidster提要,并使用它打開一個到Androidster站點的HTTP連接。這一常見行為自然是在 Java 代碼中建模,我們使用了一個抽象基類,如清單3所示。

清單 3. 基本提要解析器類

  1. public abstract class BaseFeedParser implements FeedParser { 
  2. // names of the XML tags 
  3. static final String PUB_DATE = "pubDate"
  4. static final String DESCRIPTION = "description"
  5. static final String LINK = "link"
  6. static final String TITLE = "title"
  7. static final String ITEM = "item"
  8. final URL feedUrl; 
  9. protected BaseFeedParser(String feedUrl){ 
  10. try { 
  11. this.feedUrl = new URL(feedUrl); 
  12. catch (MalformedURLException e) { 
  13. throw new RuntimeException(e); 
  14. protected InputStream getInputStream() { 
  15. try { 
  16. return feedUrl.openConnection().getInputStream(); 
  17. catch (IOException e) { 
  18. throw new RuntimeException(e); 

基類存儲 feedUrl 并使用它打開了一個 java.io.InputStream。如果出現任何差錯,它會拋出一個 RuntimeException,造成應用程序出現故障。基類還為標記的名稱定義了一些簡單的常量。清單 4 顯示了提要中的一些示例內容,以便于您理解這些標記的重要性。

清單 4.示例XML提要

  1. <?xml version="1.0" encoding="UTF-8"?> 
  2. <!-- generator="FeedCreator 1.7.2" --> 
  3. <rss version="2.0"
  4. <channel> 
  5. <title>android_news</title> 
  6. <description>android_news</description> 
  7. <link><a href="\"http://www.androidster.com/android_news.php</link>\"" target="\"_blank\"">http://www.androidster.com/android_news.php</link></a> 
  8. <lastBuildDate>Sun, 19 Apr 2009 19:43:45 +0100</lastBuildDate> 
  9. <generator>FeedCreator 1.7.2</generator> 
  10. <item> 
  11. <title>Samsung S8000 to Run Android, Play DivX, Take Over the 
  12. World</title> 
  13. <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> 
  14. play-divx-take-over-the-world</link> 
  15. <description>More details have emerged on the first Samsung handset 
  16. to run Android. A yet-to-be announced phone called the S8000 is being 
  17. reported ...</description> 
  18. <pubDate>Thu, 16 Apr 2009 07:18:51 +0100</pubDate> 
  19. </item> 
  20. <item> 
  21. <title>Android Cupcake Update on the Horizon</title> 
  22. <link><a href="\"http://www.androidster.com/android_news/android-cupcake-update-\"" target="\"_blank\"">http://www.androidster.com/android_news/android-cupcake-update-</a> 
  23. on-the-horizon</link> 
  24. <description>After months of discovery and hearsay, the Android 
  25. build that we have all been waiting for is about to finally make it 
  26. out ...</description> 
  27. <pubDate>Tue, 14 Apr 2009 04:13:21 +0100</pubDate> 
  28. </item> 
  29. </channel> 
  30. </rss> 

如清單4中的示例所示,一個ITEM對應于一個Message實例。項目的子節點(TITLE、LINK 等)對應于 Message 實例的屬性。現在,您已經對提要有了一定的認識,并且已經創建了所有常用部分,接下來看看如何使用 Android 上可用的各種技術來解析這個提要。您將從 SAX 開始。

使用 SAX

在Java環境中,當您需要一個速度快的解析器并且希望最大限度減少應用程序的內存占用時,通??梢允褂?SAX API。這非常適用于運行 Android 的移動設備。您可以在 Java 環境中照原樣使用 SAX API,在 Android 上運行它不需要做任何修改。清單 5 顯示了FeedParser 接口的一個 SAX 實現。

清單 5. SAX 實現

  1. public class SaxFeedParser extends BaseFeedParser { 
  2. protected SaxFeedParser(String feedUrl){ 
  3. super(feedUrl); 
  4. public List<Message> parse() { 
  5. SAXParserFactory factory = SAXParserFactory.newInstance(); 
  6. try { 
  7. SAXParser parser = factory.newSAXParser(); 
  8. RssHandler handler = new RssHandler(); 
  9. parser.parse(this.getInputStream(), handler); 
  10. return handler.getMessages(); 
  11. catch (Exception e) { 
  12. throw new RuntimeException(e); 

如果您以前使用過 SAX,那么這對您肯定非常熟悉。與任何 SAX 實現相同,大多數細節都在 SAX 處理程序中。在分解 XML 文檔時,處理程序從 SAX 解析器接收事件。在本例中,您創建了一個新的名稱為 RssHandler 的類,并將它注冊為解析器的處理程序,如 清單 6 所示。

清單 6. SAX 處理程序

  1. import static org.developerworks.android.BaseFeedParser.*; 
  2. public class RssHandler extends DefaultHandler{ 
  3. private List<Message> messages; 
  4. private Message currentMessage; 
  5. private StringBuilder builder; 
  6. public List<Message> getMessages(){ 
  7. return this.messages; 
  8. @Override 
  9. public void characters(char[] ch, int start, int length) 
  10. throws SAXException { 
  11. super.characters(ch, start, length); 
  12. builder.append(ch, start, length); 
  13. @Override 
  14. public void endElement(String uri, String localName, String name) 
  15. throws SAXException { 
  16. super.endElement(uri, localName, name); 
  17. if (this.currentMessage != null){ 
  18. if (localName.equalsIgnoreCase(TITLE)){ 
  19. currentMessage.setTitle(builder.toString()); 
  20. else if (localName.equalsIgnoreCase(LINK)){ 
  21. currentMessage.setLink(builder.toString()); 
  22. else if (localName.equalsIgnoreCase(DESCRIPTION)){ 
  23. currentMessage.setDescription(builder.toString()); 
  24. else if (localName.equalsIgnoreCase(PUB_DATE)){ 
  25. currentMessage.setDate(builder.toString()); 
  26. else if (localName.equalsIgnoreCase(ITEM)){ 
  27. messages.add(currentMessage); 
  28. builder.setLength(0); 
  29. @Override 
  30. public void startDocument() throws SAXException { 
  31. super.startDocument(); 
  32. messages = new ArrayList<Message>(); 
  33. builder = new StringBuilder(); 
  34. @Override 
  35. public void startElement(String uri, String localName, String name, 
  36. Attributes attributes) throws SAXException { 
  37. super.startElement(uri, localName, name, attributes); 
  38. if (localName.equalsIgnoreCase(ITEM)){ 
  39. this.currentMessage = new Message(); 

RssHandler 類擴展了 org.xml.sax.helpers.DefaultHandler 類。該類為 SAX 解析器生成的事件所對應的所有方法都提供了一個默認的非操作實現。這允許子類根據需要僅覆蓋一些方法。RssHandler 提供了一個額外的 API,即 getMessages。它返回處理程序在從 SAX 解析器接收事件時所收集的 Message 對象列表。它有另外兩個內部變量,currentMessage 針對被解析的 Message 實例,以及名稱為 builder 的 StringBuilder 變量,用于存儲文本節點中的字符數據。解析器將相應事件發送給處理程序時會調用 startDocument 方法,這兩個變量的初始化操作就是在此時完成。

查看清單6中的startElement方法。在XML文檔中每次遇到開始標記時都會調用它。您只關心該標記何時為ITEM標記。對于這種情況,您將創建一個新的Message。現在來看characters方法。遇到文本節點中的字符數據時便會調用此方法。數據只是被添加到builder變量中。最后,我們來看endElement方法。遇到結束標記時會調用此方法。對于與某Message屬性相對應的標記,如TITLE和LINK,則使用builder變量中的數據在currentMessage上設置適當的屬性。如果結束標記是一個ITEM,則currentMessage將被添加到Messages列表中。所有這些都是非常典型的SAX解析;此處的一切都不是Android所特有的。因此,如果您知道如何編寫Java SAX解析器,則應該知道如何編寫Android SAX解析器。但是,Android SDK確實在SAX上添加了一些便捷的特性。

別走開,精彩下頁繼續

#p#

更加簡單的 SAX 解析

Android SDK 提供了一個名稱為android.util.Xml的實用類。清單 7 展示了如何使用這個相同的實用類來設置一個 SAX 解析器。

清單 7. Android SAX 解析器

  1. public class AndroidSaxFeedParser extends BaseFeedParser { 
  2. public AndroidSaxFeedParser(String feedUrl) { 
  3. super(feedUrl); 
  4. public List<Message> parse() { 
  5. RssHandler handler = new RssHandler(); 
  6. try { 
  7. Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, handler); 
  8. catch (Exception e) { 
  9. throw new RuntimeException(e); 
  10. return handler.getMessages(); 

注意,這個類仍然使用了一個標準的 SAX 處理程序,因此您僅僅重用了 清單 7 中所示的 RssHandler。能夠重用 SAX 處理程序是非常不錯的,但其代碼稍微有些復雜。您可以想像,如果需要解析一個更加復雜的 XML 文檔,則處理程序可能會帶來各種各樣的 bug。舉例來說,回頭看看 清單 6 中的 endElement 方法。注意,在嘗試設置屬性之前,它檢查了 currentMessage 是否為 null?,F在,再回頭看看 清單 4 中的示例 XML。 注意,ITEM 標記外部有一些 TITLE 和 LINK 標記。這就是使用 null 檢查的原因。否則,每一個 TITLE標記 會導致一個 NullPointerException。Android 提供了自己獨有的 SAX API(參見 清單 8),它排除了您編寫自己的 SAX 處理程序的需要。

清單 8. 經過簡化的 Android SAX 解析器

  1. public class AndroidSaxFeedParser extends BaseFeedParser { 
  2. public AndroidSaxFeedParser(String feedUrl) { 
  3. super(feedUrl); 
  4. public List<Message> parse() { 
  5. final Message currentMessage = new Message(); 
  6. RootElement root = new RootElement("rss"); 
  7. final List<Message> messages = new ArrayList<Message>(); 
  8. Element channel = root.getChild("channel"); 
  9. Element item = channel.getChild(ITEM); 
  10. item.setEndElementListener(new EndElementListener(){ 
  11. public void end() { 
  12. messages.add(currentMessage.copy()); 
  13. }); 
  14. item.getChild(TITLE).setEndTextElementListener(new EndTextElementListener(){ 
  15. public void end(String body) { 
  16. currentMessage.setTitle(body); 
  17. }); 
  18. item.getChild(LINK).setEndTextElementListener(new EndTextElementListener(){ 
  19. public void end(String body) { 
  20. currentMessage.setLink(body); 
  21. }); 
  22. item.getChild(DESCRIPTION).setEndTextElementListener(new 
  23. EndTextElementListener(){ 
  24. public void end(String body) { 
  25. currentMessage.setDescription(body); 
  26. }); 
  27. item.getChild(PUB_DATE).setEndTextElementListener(new EndTextElementListener(){ 
  28. public void end(String body) { 
  29. currentMessage.setDate(body); 
  30. }); 
  31. try { 
  32. Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, 
  33. root.getContentHandler()); 
  34. catch (Exception e) { 
  35. throw new RuntimeException(e); 
  36. return messages; 

新的SAX 解析代碼并未使用 SAX 處理程序,而是使用了 SDK 中的 android.sax 包中的類。這些類允許您構建 XML 文檔的結構,并根據需要添加事件監聽程序。在以上代碼中,您聲明文檔將有一個 rss 根元素,并且它有一個 channel 子元素。然后,您聲明channel 將有一個 ITEM 子元素,并且開始添加監聽程序。對于每個監聽程序,您都使用了一個實現了特定接口(EndElementListner或 EndTextElementListener)的匿名內部類。注意,您不需要跟蹤字符數據。不僅僅因為這樣會更加簡單,更重要的是更加高效。最后,在調 用 Xml.parse 實用方法時,您將傳遞一個通過根元素生成的處理程序。

清單 8 中的所有代碼都是可選的。如果您習慣 Java 環境中的標準 SAX 解析代碼,那么您可以堅持使用它。如果您希望嘗試 Android SDK 所提供的便捷的包裝器,那么也可以使用它。如果您完全不希望使用 SAX 會怎樣呢?可以使用一些備選方案。其中的首選方法就是 DOM。

使用 DOM

Android 完全支持 DOM 解析,就像在桌面機器或服務器上使用 Java 代碼運行它一樣。清單 9 顯示了一個基于 DOM 的解析器接口實現。

清單 9. 基于 DOM 的提要解析器實現

  1. public class DomFeedParser extends BaseFeedParser { 
  2. protected DomFeedParser(String feedUrl) { 
  3. super(feedUrl); 
  4. public List<Message> parse() { 
  5. DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 
  6. List<Message> messages = new ArrayList<Message>(); 
  7. try { 
  8. DocumentBuilder builder = factory.newDocumentBuilder(); 
  9. Document dom = builder.parse(this.getInputStream()); 
  10. Element root = dom.getDocumentElement(); 
  11. NodeList items = root.getElementsByTagName(ITEM); 
  12. for (int i=0;i<items.getLength();i++){ 
  13. Message message = new Message(); 
  14. Node item = items.item(i); 
  15. NodeList properties = item.getChildNodes(); 
  16. for (int j=0;j<properties.getLength();j++){ 
  17. Node property = properties.item(j); 
  18. String name = property.getNodeName(); 
  19. if (name.equalsIgnoreCase(TITLE)){ 
  20. message.setTitle(property.getFirstChild().getNodeValue()); 
  21. else if (name.equalsIgnoreCase(LINK)){ 
  22. message.setLink(property.getFirstChild().getNodeValue()); 
  23. else if (name.equalsIgnoreCase(DESCRIPTION)){ 
  24. StringBuilder text = new StringBuilder(); 
  25. NodeList chars = property.getChildNodes(); 
  26. for (int k=0;k<chars.getLength();k++){ 
  27. text.append(chars.item(k).getNodeValue()); 
  28. message.setDescription(text.toString()); 
  29. else if (name.equalsIgnoreCase(PUB_DATE)){ 
  30. message.setDate(property.getFirstChild().getNodeValue()); 
  31. messages.add(message); 
  32. catch (Exception e) { 
  33. throw new RuntimeException(e); 
  34. return messages; 

與第一個 SAX 示例類似,以上代碼完全沒有特定于 Android 的地方。DOM 解析器將所有 XML 文檔讀取到內存中,然后允許您使用 DOM API 遍歷 XML 樹、檢索所需的數據。這是非常直觀的代碼,并且,在某些方面比基于 SAX 的實現更加簡單。但是,DOM 通常更加占用內存,因為一切內容都會先讀取到內存中。這對于運行 Android 的移動設備來說是一個問題,但是當 XML 文檔始終保持很小的大小時是可行的。這可能意味著,Android 的開發人員會認為 SAX 解析在 Android 應用程序上更加常見,因此為它提供了額外的實用工具。Android 還提供了另一種類型的 XML 解析器,它就是 pull 解析器。

XML pull 解析器

如前所述,Android 并未提供對 Java StAX API 的支持。但是,Android 確實附帶了一個 pull 解析器,其工作方式類似于 StAX。它允許您的應用程序代碼從解析器中獲取事件,這與 SAX 解析器自動將事件推入處理程序相反。清單 10 顯示了提要解析接口的一個 pull 解析器實現。

清單 10. 基于 Pull 解析器的實現

  1. public class XmlPullFeedParser extends BaseFeedParser { 
  2. public XmlPullFeedParser(String feedUrl) { 
  3. super(feedUrl); 
  4. public List<Message> parse() { 
  5. List<Message> messages = null
  6. XmlPullParser parser = Xml.newPullParser(); 
  7. try { 
  8. // auto-detect the encoding from the stream 
  9. parser.setInput(this.getInputStream(), null); 
  10. int eventType = parser.getEventType(); 
  11. Message currentMessage = null
  12. boolean done = false
  13. while (eventType != XmlPullParser.END_DOCUMENT && !done){ 
  14. String name = null
  15. switch (eventType){ 
  16. case XmlPullParser.START_DOCUMENT: 
  17. messages = new ArrayList<Message>(); 
  18. break
  19. case XmlPullParser.START_TAG: 
  20. name = parser.getName(); 
  21. if (name.equalsIgnoreCase(ITEM)){ 
  22. currentMessage = new Message(); 
  23. else if (currentMessage != null){ 
  24. if (name.equalsIgnoreCase(LINK)){ 
  25. currentMessage.setLink(parser.nextText()); 
  26. else if (name.equalsIgnoreCase(DESCRIPTION)){ 
  27. currentMessage.setDescription(parser.nextText()); 
  28. else if (name.equalsIgnoreCase(PUB_DATE)){ 
  29. currentMessage.setDate(parser.nextText()); 
  30. else if (name.equalsIgnoreCase(TITLE)){ 
  31. currentMessage.setTitle(parser.nextText()); 
  32. break
  33. case XmlPullParser.END_TAG: 
  34. name = parser.getName(); 
  35. if (name.equalsIgnoreCase(ITEM) && 
  36. currentMessage != null){ 
  37. messages.add(currentMessage); 
  38. else if (name.equalsIgnoreCase(CHANNEL)){ 
  39. done = true
  40. break
  41. eventType = parser.next(); 
  42. catch (Exception e) { 
  43. throw new RuntimeException(e); 
  44. return messages; 

pull 解析器的運行方式與 SAX 解析器相似。它提供了類似的事件(開始元素和結束元素),但您需要使用 (parser.next() 提取它們。事件將作為數值代碼被發送,因此您可以使用一個簡單 case-switch。注意,解析并未像 SAX 解析那樣監聽元素的結束,而是在開始處完成了大部分處理。在 清單 10 的代碼中,當某個元素開始時,您可以調用 parser.nextText() 從 XML 文檔中提取所有字符數據。還需注意,您設置了一個標記(布爾變量 done)來確定何時到達感興趣內容的結束部分。這允許您提早停止讀取 XML 文檔,因為您知道代碼將不會關心文檔的其余部分。這有時非常實用,特別是當您只需要訪問一小部分 XML 文檔時。通過盡快停止解析,您可以極大地減少解析時間。這種優化對于連接速度較慢的移動設備尤為重要。pull 解析器可以提供一些性能優勢以及易用性。它還可以用于編寫 XML。

創建 XML

目前為止,我一直專注于通過 Internet 解析 XML。但是,有時您的應用程序可能需要將 XML 發送到遠程服務器。顯然,您可以只使用一個 StringBuilder 來創建 XML 字符串。另一種備選方法來自 清單 11 中的 Pull 解析器。

清單 11. 使用 pull 解析器編寫 XML

  1. private String writeXml(List<Message> messages){ 
  2. XmlSerializer serializer = Xml.newSerializer(); 
  3. StringWriter writer = new StringWriter(); 
  4. try { 
  5. serializer.setOutput(writer); 
  6. serializer.startDocument("UTF-8"true); 
  7. serializer.startTag("""messages"); 
  8. serializer.attribute("""number", String.valueOf(messages.size())); 
  9. for (Message msg: messages){ 
  10. serializer.startTag("""message"); 
  11. serializer.attribute("""date", msg.getDate()); 
  12. serializer.startTag("""title"); 
  13. serializer.text(msg.getTitle()); 
  14. serializer.endTag("""title"); 
  15. serializer.startTag("""url"); 
  16. serializer.text(msg.getLink().toExternalForm()); 
  17. serializer.endTag("""url"); 
  18. serializer.startTag("""body"); 
  19. serializer.text(msg.getDescription()); 
  20. serializer.endTag("""body"); 
  21. serializer.endTag("""message"); 
  22. serializer.endTag("""messages"); 
  23. serializer.endDocument(); 
  24. return writer.toString(); 
  25. catch (Exception e) { 
  26. throw new RuntimeException(e); 

XmlSerializer 類是 前一部分 所使用的 XmlPullParser 包的一部分。它沒有提取事件,而是將它們推出到數據流或編寫程序中。在本例中,它僅僅將事件推送到了一個 java.io.StringWriter 實例中。它提供了一個直觀的 API,通過各種方法開始和結束文檔、處理元素以及添加文本或屬性。這是StringBuilder的一種出色的替換方案,因為它可以更加輕松地確保您的 XML 具有良好結構。

結束語

您希望為Android設備構建何種類型的應用程序?無論如何,如果它需要通過 Internet 使用數據,那么都可能需要使用XML。在本文中,您看到 Android 提供了大量用于處理XML的工具。您可以選擇其中之一作為自己的工具,或者您可以根據用例來進行選擇。大多數時間,使用SAX是比較安全的,并且Android提供了一種傳統的SAX 使用方法,以及一個便捷的SAX包裝器。如果您的文檔比較小,那么DOM可能是一種比較簡單的方法。如果您的文檔比較大,但您只需要文檔的一部分,則XML Pull解析器可能是更為有效的方法。最后,對于編寫XML,Pull解析器包也提供了一種便捷的方法。因此,無論您的XML需求如何,Android都能在一定程度上滿足它們。

責任編輯:閆佳明 來源: my.eoe.cn
相關推薦

2009-02-20 11:43:22

UNIXfish全攻略

2009-07-17 17:43:49

Jruby開發Web

2010-04-23 14:04:23

Oracle日期操作

2024-05-07 09:01:21

Queue 模塊Python線程安全隊列

2013-04-15 10:48:16

Xcode ARC詳解iOS ARC使用

2023-10-13 19:42:00

2009-12-14 14:32:38

動態路由配置

2009-10-19 15:20:01

家庭綜合布線

2014-03-19 17:22:33

2021-01-29 17:40:00

Flyme安卓手機安全

2011-07-19 20:36:56

2021-04-23 20:59:02

ThreadLocal內存

2020-03-05 09:53:59

ElasticSearLuceneJava

2015-03-04 13:53:33

MySQL數據庫優化SQL優化

2022-10-21 11:30:42

用戶生命周期分析

2009-10-12 15:06:59

2009-07-04 11:26:12

unix應急安全攻略

2010-10-11 13:54:03

Windows Ser

2020-12-28 10:50:09

Linux環境變量命令

2009-02-12 10:12:00

NAT配置
點贊
收藏

51CTO技術棧公眾號

黄页网站在线| 一区二区三区免费观看视频| 亚洲制服一区| 欧美日韩你懂的| 激情六月天婷婷| 视频在线不卡| 激情五月婷婷综合| 97在线观看免费高清| a天堂中文字幕| √8天堂资源地址中文在线| www.日本不卡| 91禁外国网站| 五月综合色婷婷| 99久久香蕉| 日本高清不卡视频| 国产又爽又黄ai换脸| 亚洲精品久久久狠狠狠爱| 在线视频精品| 北条麻妃一区二区三区中文字幕| 麻豆传媒在线看| 樱花草涩涩www在线播放| 久久免费看少妇高潮| 成人综合网网址| 日韩精品一区二区不卡| 热久久天天拍国产| 日韩欧美一级特黄在线播放| 国产免费毛卡片| 国产网站在线免费观看| 99re视频精品| 成人午夜在线影院| 天天操天天操天天操天天| 雨宫琴音一区二区三区| 亚洲欧美日韩天堂一区二区| 欧美污在线观看| av亚洲一区二区三区| 一个色妞综合视频在线观看| 日韩久久久久久久久久久久久| 精品国产一级片| 美女久久网站| 久久久亚洲精选| 精品一区二区在线观看视频| 欧美自拍一区| 欧美一级艳片视频免费观看| 成人三级视频在线播放 | 亚洲一区第一页| 中文字幕乱码人妻综合二区三区| 成人短视频在线| 久久九九久精品国产免费直播| 粉嫩av免费一区二区三区| 免费在线不卡av| 亚洲青涩在线| 欧美理论电影在线观看| 蜜桃视频最新网址| 欧美人妖在线| 日韩电影免费观看中文字幕| 自拍偷拍激情视频| 四虎精品在线观看| 欧美网站一区二区| 成人午夜视频免费在线观看| 麻豆视频在线看| 一区二区三区在线视频播放| 亚洲一卡二卡| 国产福利小视频在线观看| 91在线免费视频观看| 国产精品国色综合久久| 99re只有精品| 激情综合色播激情啊| 国产成人av在线播放| 日本道在线观看| 99在线精品免费视频九九视| 欧美激情18p| 欧美日韩成人免费观看| 亚洲欧美综合| 欧美美女操人视频| 私库av在线播放| 亚洲国产精品成人| 久久综合久久美利坚合众国| 91视频青青草| 欧美区日韩区| 午夜精品在线观看| 国产成人无码精品| 亚洲制服av| 日韩av黄色在线观看| 日韩精品一区二区亚洲av观看| 亚洲中字在线| 国产精品三级久久久久久电影| 中文字幕一区二区在线视频| 久久99国产精品久久| 国产精品成人一区二区| 欧美一区二区三区不卡视频| 日韩二区在线观看| 国产欧美日韩亚洲精品| 国产免费黄色网址| 国产成人精品免费网站| 国产在线资源一区| 瑟瑟在线观看| 中文字幕精品三区| 先锋影音男人资源| 18aaaa精品欧美大片h| 欧美性猛交xxxx乱大交极品| 波多结衣在线观看| 精品视频在线播放一区二区三区 | 成人精品视频一区二区三区尤物| 91精品在线一区| 国产夫绿帽单男3p精品视频| av亚洲精华国产精华精华 | 亚洲欧美另类日韩| 99国产一区二区三精品乱码| 欧美一区二区在线视频观看| 午夜毛片在线| 亚洲成人精品一区二区| 精品99在线视频| 日韩三级一区| 亚洲精品97久久| 日韩av片在线免费观看| 欧美久久九九| 国产91在线播放精品91| 国产精品爽爽久久| av在线不卡观看免费观看| 亚洲不卡一卡2卡三卡4卡5卡精品| 成人77777| 亚洲一卡二卡三卡四卡五卡| www.99av.com| 第一区第二区在线| 中文字幕久热精品视频在线| 日韩 欧美 精品| 久久av资源网| 久久草.com| 青青色在线视频| 亚洲一区二区三区四区的| www.99在线| xxxx日韩| 久久天堂av综合合色| 日韩精品成人免费观看视频| 国产高清久久久| 亚洲日本理论电影| 在线天堂资源www在线污| 欧美一区二区视频免费观看| 亚洲av无码一区二区三区人| 欧美激情一区| 成人福利网站在线观看| 日本福利午夜视频在线| 亚洲国产欧美日韩另类综合| 日本三级黄色网址| 亚洲资源网你懂的| 69av在线视频| 亚洲精品.www| 亚洲精品日韩一| 亚洲性图一区二区| 国产成人精品999在线观看| 国产综合在线看| 成人激情四射网| 中文字幕在线播放不卡一区| 成年人在线观看视频免费| 日本午夜精品| 午夜精品一区二区三区在线 | 国产精品制服诱惑| 五月花成人网| 日韩视频永久免费| 欧美精品久久久久久久久46p| 视频一区二区国产| 蜜桃视频在线观看成人| 51av在线| 亚洲精品福利资源站| 国产精选第一页| 国产成人午夜99999| 亚洲国产精品毛片| 日本韩国欧美| 日韩精品在线看| 极品国产91在线网站| 久久午夜老司机| 日批视频在线免费看| 日韩福利视频一区| 欧美一区二三区| 男人天堂亚洲二区| 在线免费不卡电影| 欧日韩不卡视频| 韩国av一区二区三区在线观看| 一区二区在线不卡| 国产色99精品9i| 欧美另类在线播放| 免费观看a视频| 午夜一区二区三区在线观看| 鲁大师私人影院在线观看| 免费视频一区二区三区在线观看| 欧美高清视频一区| 久久精品女人天堂av免费观看 | 国产精品自在线| 国产成人无吗| 精品国产亚洲在线| 午夜精品久久久久久久久久久久久蜜桃| 成人免费视频app| 欧美性大战久久久久xxx| 国产日产一区| 91日韩在线视频| 91在线三级| 亚洲午夜未删减在线观看| 中文字幕永久在线观看| 一区二区三区不卡在线观看| 亚洲激情 欧美| 日韩av中文字幕一区二区 | 亚洲综合小说| 激情伦成人综合小说| 日日夜夜天天综合| 久久这里只有精品99| 手机看片一区二区三区| 欧美性感一类影片在线播放| 一区二区三区影视| 不卡电影一区二区三区| 成人亚洲视频在线观看| 一精品久久久| 秋霞毛片久久久久久久久| 国产精品视频一区视频二区 | 青青青手机在线视频| 国产成人精品免费看| 成人免费xxxxx在线视频| 中文字幕一区二区三区久久网站| 国产乱人伦精品一区二区| 欧美不卡高清一区二区三区| 欧美高清在线观看| 第三区美女视频在线| 欧美va亚洲va在线观看蝴蝶网| www五月天com| 有码一区二区三区| 国产美女免费网站| 国产成人免费在线| 九热视频在线观看| 亚洲免费成人| 大片在线观看网站免费收看| 国产成人一区| 国产伦理久久久| 伊人久久一区| 国产精品大陆在线观看| a毛片在线观看| 亚洲女人被黑人巨大进入| 99精品久久久久久中文字幕| 欧美综合色免费| 中文字幕av影院| 亚洲国产va精品久久久不卡综合 | 亚洲在线一区二区三区| 欧美美女性生活视频| 久久久噜噜噜久久人人看| 久久久无码人妻精品无码| 美女一区二区三区| 黄色国产精品视频| 999在线观看精品免费不卡网站| 午夜在线视频免费观看| 欧美日韩国产免费观看视频| 国内精品久久国产| 亚洲乱码一区| 91在线网站视频| 亚洲久草在线| 国产欧美中文字幕| 秋霞国产精品| 国产精品video| 成人美女大片| 欧美一级片一区| 99re6在线精品视频免费播放| 欧美超级免费视 在线| 国产乱色在线观看| 精品国产自在精品国产浪潮| aaa在线观看| 一区二区三区www| 九色在线免费| 久久精品国产亚洲精品2020| 97在线观看免费观看高清 | 一区在线视频| 国产一区二区三区小说| 国产精品99免费看| 国产精品视频网站在线观看| 国产伊人精品| 成人免费性视频| 一区福利视频| 欧美日韩在线中文| 美女久久一区| 激情五月俺来也| 久久av资源网| 国产毛片久久久久久| 国产suv精品一区二区883| 91亚洲一线产区二线产区 | 亚洲高清视频中文字幕| 日本在线小视频| 在线观看国产一区二区| 中文字幕一区二区三区免费看 | 国产原创精品| 天海翼亚洲一区二区三区| 免费国产一区二区| 精品日韩在线| 日本一本草久p| 亚洲国产一区二区三区a毛片| 免费看一级大黄情大片| 久久精品二区三区| 91视频这里只有精品| 国产成人在线看| 一区二区视频观看| 国产精品欧美久久久久一区二区| 一区二区三区四区五区| 亚洲超碰97人人做人人爱| 综合网在线观看| 欧美日韩国产bt| 肥臀熟女一区二区三区| 亚洲男人天天操| 国产精品刘玥久久一区| www.欧美免费| av剧情在线观看| 国产精品精品一区二区三区午夜版| 蜜桃视频成人m3u8| 国产精品久久视频| 91麻豆精品激情在线观看最新| 久热这里只精品99re8久| 国产精品99视频| 免费欧美一级视频| 狠狠色伊人亚洲综合成人| 女同性恋一区二区三区| 中文字幕视频一区二区三区久| 国产精品18p| 欧美日韩久久不卡| 欧美一区二区三区激情| 色多多国产成人永久免费网站 | 色阁综合伊人av| 波多野结衣中文字幕久久| 国产精品欧美亚洲777777| 97久久综合区小说区图片区| 五月天亚洲综合小说网| 亚洲国产欧美国产综合一区| 艹b视频在线观看| aa级大片欧美| 国产一区二区播放| 日本高清不卡视频| 蜜臀av中文字幕| 久久伊人色综合| 国产香蕉久久| 久热这里只精品99re8久 | 粉嫩一区二区三区在线看| 综合 欧美 亚洲日本| 欧美日韩午夜剧场| 午夜精品久久久久久久爽 | 色哟哟国产精品色哟哟| 亚洲天堂成人在线视频| 国产理论电影在线| 国产专区欧美专区| 日韩精品一区二区久久| 女性女同性aⅴ免费观女性恋| 丁香五精品蜜臀久久久久99网站 | 免费福利视频一区| 50度灰在线观看| 精品夜夜嗨av一区二区三区| 性欧美一区二区| 日本精品一级二级| 亚洲区小说区图片区| 国模gogo一区二区大胆私拍| 久久综合偷偷噜噜噜色| 亚洲午夜精品久久久久久浪潮| 日韩av网站在线观看| 亚洲天堂久久新| 黑人极品videos精品欧美裸| 天天爽夜夜爽夜夜爽| 97国产一区二区精品久久呦| 天堂va欧美ⅴa亚洲va一国产| 综合视频在线观看| 美日韩一级片在线观看| 萌白酱视频在线| 欧美日高清视频| 男人的天堂在线视频免费观看 | 亚洲精品无码久久久久| 亚洲人成电影网| 色婷婷综合久久久中字幕精品久久 | 青青青在线免费观看| 91精品麻豆日日躁夜夜躁| 求av网址在线观看| 国产精品美女免费看| 亚洲人成精品久久久| 欧美日韩一区二区在线免费观看| 久久综合av免费| 欧美人一级淫片a免费播放| 国产亚洲精品久久久| 精品国产欧美日韩一区二区三区| 视频一区二区精品| 久久99精品久久久久久动态图| 国精产品视频一二二区| 91精品婷婷国产综合久久竹菊| 国产秀色在线www免费观看| 99蜜桃在线观看免费视频网站| 欧美日韩ab| 免费在线观看成年人视频| 色av成人天堂桃色av| 在线国产91| 51蜜桃传媒精品一区二区| 在线日韩视频| 精品人伦一区二区| 欧美日韩国产成人在线免费| 色www永久免费视频首页在线| 精品国产免费久久久久久尖叫| 另类亚洲自拍| 亚洲女同二女同志奶水| 精品欧美黑人一区二区三区| 黑人巨大精品| 在线丝袜欧美日韩制服| 成人性生交大片免费看视频在线| 国产免费av一区二区|