- 浏览: 64794 次
- 性别:
- 来自: 北京
-
最新评论
-
zlj_fly:
学习了~~
context是如何泄漏的 - Handlers和内部类 -
shiylqq:
启发很大,谢谢啦!
SQLite 批量insert - 如何加速SQLite的插入操作 -
hbxflihua:
...
如何增加android模拟器的ROM(内部存储空间) -
hchaojie:
sdh5724 写道一开始就不0O,就不模式,等于慢性自殺对于 ...
appengine+gwt使用日记 - 持久化字段超过500字节的问题 -
sdh5724:
一开始就不0O,就不模式,等于慢性自殺
appengine+gwt使用日记 - 持久化字段超过500字节的问题
(翻译自http://www.ibm.com/developerworks/opensource/library/x-android/)
写代码迟早都得跟xml打交道,java有两种常见的xml处理方式:SAX和DOM,在android平台上都可以用。另外,StAX是一种新的xml处理方式,android还没有提供原生支持,但是提供了一个功能类似的库 - XML pull parser,三种方式的使用分别如下。
- 首先,我们要处理的xml长得像这样(rss feed):
<?xml version="1.0" encoding="UTF-8"?> <rss version="2.0" > <channel> <title> android_news </title> <description> android_news </description> <link> http://www.androidster.com/android_news.php </link> <item> <title> Samsung S8000 to Run Android, Play DivX, Take Over the World </title> <link> http://www.androidster.com/android_news/</link> <description>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> http://www.androidster.com/android_news/android-cupcake-update- on-the-horizon </link> <description> 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
这是一个rss feed,我们要提取其中的item信息,我们可以先为item定义一个数据模型(pojo):
public class Message { private 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; public void setLink(String link) { try { this.link = new URL(link); } catch (MalformedURLException e) { throw new RuntimeException(e); } } public void setDate(String date) { try { this.date = FORMATTER.parse(date.trim()); } catch (ParseException e) { throw new RuntimeException(e); } } // 省略其他的getter, setter }
- 因为我们要采用几种方式来解析xml,因此我们可以定义一个基本的解析接口:
public interface FeedParser { List<Message> parse(); }
所有的parser都需要通过一个url从网络获取feed数据,我们可以让url在parser对象构造的时候传入,
下面是我们定义的一个基本的解析类:
public abstract class BaseFeedParser implements FeedParser { // 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); } } }
方式一:使用SAX
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); } } }或者,用android提供的xml工具类更简单:
import android.util.Xml; 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的处理的重点在于,我们需要定义一个handler来解析,这个handler可以继承自:
org.xml.sax.helpers.DefaultHandler 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(); } } }
这是SAX处理的典型方式,处理简单的文档还是很方便。不过,如果xml结构变得复杂,上述方式就容易出错,
因为在处理标签的时候,我们需要知道该标签的结构层次,为此我们需要定义一些额外的实例变量(currentMessage),
android提供了SAX API的另一种使用方式,使得我们不需要写自己的handler:
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); } }); // 其他字段省略 try { Xml.parse(this.getInputStream(), Xml.Encoding.UTF_8, root.getContentHandler()); } catch (Exception e) { throw new RuntimeException(e); } return messages; } }这种方式的特点是,你先手动建立xml的结构模型,然后在需要处理的节点上注册一个 EndTextElementListener。
方式二:使用DOM
DOM的特点是简单直观,处理小文档非常方便。它一次把文档读入内存,然后你可以用DOM API 来遍历文档,获取所需数据。当然,如果文档较大,它就比较耗内存了。
因此,在移动平台,你可以想象SAX比DOM使用得更普遍。
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; } }
方式三:xml pull parser。
上面提到过StAX,android上面没有这个,但是xml pull parser是类似的东西,pull是拉的意思,为啥跟拉相关呢?首先,我们可以把SAX理解为--向handler不断”推送”事件,pull parser相反,它是从parse拉取或者说寻找事件:
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; } }
xml pull parser 比SAX多了一个循环,它不断调用parser.next()读取事件。值得注意的一点是,你可以随时终止while循环,比如你只需要读取到某一个节点时。
总结:
- android平台上,大多时候SAX是一个安全的选择
- 如果文档很小,DOM用起来更简单。
- 文档很大,并且你只需要文档的一部分,那么xml pull parser更高效。
相关推荐
XML数据在网络通信中通常与HTTP协议结合,通过`java.net.HttpURLConnection`或`android.util.JsonReader`进行网络请求和响应的处理。 在实际开发中,选择哪种解析方式取决于具体需求。DOM适合小规模且需要频繁修改...
在Android应用开发中,Fragment是Android SDK提供的一种组件,它允许开发者在单个Activity中实现多个可交互的屏幕区域。Fragment的设计使得应用可以更好地适应不同的屏幕尺寸和配置,如手机和平板。本教程将深入讲解...
- `android.util.Xml`:Android提供的一个简化版的XML处理工具,封装了上述包的功能,使得XML操作更加简洁。 4. **XML读取示例(DOM)** - 以下是一个简单的使用DOM解析XML文件的Java代码示例: ```java import...
在Android开发中,XML(可扩展标记语言)和JSON(JavaScript Object Notation)都是常见的数据交换格式。XML因其结构化特性适用于复杂的文档存储,而JSON则以其轻量级、易于阅读和编写的特点广泛用于Web服务的数据...
为了更好地理解如何在Android中解析XML文件,我们先来看一个具体的XML文件示例: ```xml <?xml version="1.0" encoding="UTF-8"?> 李明 <age>30 李向梅 <age>25 ``` #### 三、JavaBean类定义 为了...
在Android开发中,XML文件常用于存储数据、配置文件或者作为接口返回的数据格式。本教程将详细介绍如何在Android环境下解析XML文件,以...了解并掌握这些知识,将有助于你高效地在Android应用中处理XML文件。
在Android开发中,XML文件广泛用于存储数据、配置和布局。理解如何解析XML文件是至关重要的,本节将深入探讨Android中的三种XML解析方法:SAX、DOM和Pull解析。 **SAX解析** SAX(Simple API for XML)是一种基于...
在Android开发中,XML文件广泛用于存储数据、配置文件以及应用程序间的数据交换。本文将深入探讨如何使用SAX、DOM和Pull解析器解析XML文件,以及如何生成XML文件。我们将同时展示Java和Kotlin两种语言的实现方法。 ...
在Android开发中,XML(eXtensible Markup Language)是一种常用的数据存储和交换格式,用于定义用户界面布局、配置文件以及数据传输等。本篇将深入探讨XML在Android中的操作,包括XML的读取(Pull解析)和XML的生成...
在Android平台上,有时候我们需要处理Excel数据,例如读取其中的内容并转换为XML文件,以便更好地在应用程序中使用或与其他系统交换数据。这个项目提供了一种方法来实现这一目标,利用了jxl.jar库来处理Excel文件,...
本文将深入探讨Android中的XML应用及其重要性,并通过具体的代码示例来帮助读者更好地理解这一主题。 #### 二、Android与XML的基本概念 ##### 1. Android应用结构与XML - **Activity**:Android应用的核心组成...
为了方便管理这些多语言资源,Android使用`String.xml`文件来存储应用中的文本字符串。然而,手动编辑这些XML文件既耗时又容易出错,尤其是在处理大量文本时。这时,就需要借助一些工具进行`String.xml`与Excel之间...
在Android开发中,XML文件常用于存储数据、配置或布局信息。XML(eXtensible Markup Language)是一种结构化标记语言,易于阅读和编写,同时机器也能方便地解析和生成。本篇将深入探讨Android中解析XML文件的方法,...
在Android开发中,经常需要处理XML格式的数据。本篇文章将通过一个具体的例子来详细介绍如何在Android应用中解析XML文件。 首先,我们来看一下这个例子中的XML数据原型: ```xml <?xml version="1.0" encoding=...
在Android开发中,XML(eXtensible Markup Language)是一种常用的数据交换格式,常用于存储和传输结构化数据。本示例将详细讲解如何在Android应用程序中解析XML以实现类似网易客户端的功能。首先,让我们了解XML...
本篇文章将详细介绍如何在Android中对APK包中的XML文件进行解密,以及这一过程涉及的相关技术。 首先,我们需要理解APK的结构。APK本质上是一个ZIP文件,包含以下关键部分: 1. **AndroidManifest.xml**:这是应用...
在Android开发中,XML(可扩展标记语言)作为一种常见的数据交换格式,被广泛用于存储和传输数据。XML的解析方式有多种,其中SAX、DOM和PULL是Android平台常用的三种解析器。以下将详细解释这三种解析方法,并提供...
在Android开发中,XML(eXtensible Markup Language)是一种常用的数据交换格式,用于存储和传输数据。XML解析是将XML文档转换为程序可以理解的数据结构的过程。Android提供了两种主要的XML解析方式:DOM(Document ...
XML(eXtensible Markup Language)是一种用于标记数据的语言,广泛应用于Android开发中,用于存储配置、布局等信息。在Android系统中,XML Pull解析是一种轻量级且高效的解析XML文档的方法,它允许应用程序按需读取...
在Android开发中,XML是一种广泛使用的数据格式,用于存储和传输结构化数据。XML解析是将XML文件转换为应用程序可以处理的数据的过程。...熟练掌握这些技巧,将有助于你更好地处理Android应用中的XML数据。