Android 通过Dom, Sax, Pull解析网络xml数据
这篇文章不是完全原创,XML解析的部分参考了 liuhe688 的文章。文章地址:http://blog.csdn.net/liuhe688/article/details/6415593
这是一个几乎完整的过程。覆盖面也比较广。应用了AsyncTask, BaseAdapter, ListView, Dom, Sax, Pull等,这些也是开发应用中必不可少的部分。
效果图:

首先,做了些准备工作。down了一份xml数据放在本地服务器上

定义了一个model。
book.java
package com.example.phonedemo.model;
public class Book {
private int id;
private String name;
private float price;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public float getPrice() {
return price;
}
public void setPrice(float price) {
this.price = price;
}
}
1、客户端发起请求,
这是通过AsyncTask异步发起的请求。
AsyncTask 主要需要复写四个方法:
onProExecute():这个方法会在UI线程中调用 execute(..)之后立即执行,在开发中通常做一些初始化和加载UI显示的工作。
doInBackground(String... params):比较费时的操作,可以放在这里。网络请求等...
onProgressUpdate(Integer... values):通常,我们在耗时操作时候,比如download,会有一个百分比进度。在doInBackground()方法中调用
publishProgress()方法后,系统会调用此方法,更新进度信息。
onPostExecute(InputStream result):执行完毕以后调用的方法。
2、服务器端返回xml数据,
3、客户端解析数据,最终呈现出来
我用了三种解析方法,参照上述blog的地址。不过,在他得代码中稍有问题。ID是没有的。我在我的代码中改正了。
三种方式都是解析一个xml,所以写了一个接口文件。
BookParserImpl.java
package com.example.phonedemo.util; import java.io.InputStream;
import java.util.List; import com.example.phonedemo.model.Book; public interface BookParserImpl {
public List<Book> parse(InputStream is); public String serialize(List<Book> books);
}
然后,三种解析分别实现它即可。
Dom解析方式
优点:功能齐全,强大。缺点:因为需要完全加载文档,导致,比较耗资源。前辈说j2ee中用的较多。
我虽然也学Java,但是一直都与前台打交道。曾经学的东西,工作中不用,就全忘了。罪过,罪过...
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = builder.parser(InputStream input);
上述dom初始化解析实例的代码。
DomBookParser.java
package com.example.phonedemo.util; import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory; import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList; import com.example.phonedemo.model.Book; public class DomBookParser implements BookParserImpl { @Override
public List<Book> parse(InputStream is) {
List<Book> list = new ArrayList<Book>();
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = null;
Document doc = null;
try {
builder = factory.newDocumentBuilder();
doc = builder.parse(is);
NodeList itemList = doc.getDocumentElement().getElementsByTagName(
"book");
for (int i = 0; i < itemList.getLength(); i++) {
Book book = new Book();
Node node = itemList.item(i);
NodeList child = node.getChildNodes();
NamedNodeMap attr = node.getAttributes();
book.setId(Integer.parseInt(attr.getNamedItem("id")
.getNodeValue()));
for (int j = 0; j < child.getLength(); j++) {
Node childItem = child.item(j);
String nodeName = childItem.getNodeName();
if (nodeName.equals("name")) {
book.setName(childItem.getFirstChild().getNodeValue());
} else if (nodeName.equals("price")) {
book.setPrice(Float.parseFloat(childItem
.getFirstChild().getNodeValue()));
}
} list.add(book);
} } catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
} @Override
public String serialize(List<Book> books) {
// TODO Auto-generated method stub
return null;
}
}
Sax解析方式
sax是事件驱动型的,比起dom来更加灵巧。也更加简单快速。
SaxBookParser.java
package com.example.phonedemo.util; import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler; import com.example.phonedemo.model.Book; public class SaxBookParser implements BookParserImpl { @Override
public List<Book> parse(InputStream is) {
// TODO Auto-generated method stub
SAXParserFactory factory = SAXParserFactory.newInstance();
MyHandler handler = null;
try {
SAXParser parser = factory.newSAXParser();
handler = new MyHandler();
parser.parse(is, handler);
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return handler.getBooks();
} /**
* <b>解析xml的辅助类</b><br />
* <b>startDocument()</b> 当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。<br />
* <b>endDocument()</b> 和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。 <br/>
* <b>startElement(String namespaceURI, String localName, String qName,
* Attributes atts)</b>当读到一个开始标签的时候,会触发这个方法。<br />
* <b>endElement(String uri, String localName, String name)</b>
* 这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。<br />
* <b>characters(char[] ch, int start, int length)</b>
* 这个方法用来处理在XML文件中读到的内容,第一个参数用于存放文件的内容,<br />
* 后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。
*
* @author qxj
*
*/
class MyHandler extends DefaultHandler { private List<Book> books;
private Book book;
private StringBuilder builder; public List<Book> getBooks() {
return books;
} /**
* 接收元素中字符数据的通知。
*
* @param ch
* - 字符。
* @param start
* - 字符数组中的开始位置。
* @param length
* - 从字符数组中使用的字符数。
*/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
builder.append(ch, start, length);
} /**
* 接收元素结束的通知
*
* @param uri
* - 名称空间 URI,如果元素没有任何名称空间 URI,或者没有正在执行名称空间处理,则为空字符串。
* @param localName
* - 本地名称(不带前缀),如果没有正在执行名称空间处理,则为空字符串。
* @param qName
* - 限定的名称(带有前缀),如果限定的名称不可用,则为空字符串。
* @exception SAXException
* - 任何 SAX 异常,可能包装另外的异常。
*/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
if (localName.equals("book")) {
books.add(book);
} else if (localName.equals("name")) {
book.setName(builder.toString());
} else if (localName.equals("price")) {
book.setPrice(Float.parseFloat(builder.toString()));
}
} /**
* 接收文档的开始的通知
*
* @exception - SAXException - 任何 SAX 异常,可能包装另外的异常
*/
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
books = new ArrayList<Book>();
builder = new StringBuilder();
} /**
* 接收元素开始的通知。
*
* @param uri
* - 名称空间 URI,如果元素没有任何名称空间 URI,或者没有正在执行名称空间处理,则为空字符串。
* @param localName
* - 本地名称(不带前缀),如果没有正在执行名称空间处理,则为空字符串。
* @param qName
* - 限定的名称(带有前缀),如果限定的名称不可用,则为空字符串。
* @param attributes
* - 附加到元素的属性。如果没有属性,则它将是空的 Attributes 对象。
* @exception SAXException
* - 任何 SAX 异常,可能包装另外的异常
*/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
if (localName.equals("book")) {
book = new Book();
if (attributes != null) {
book.setId(Integer.parseInt(attributes.getValue("id")));
}
}
builder.setLength(0);
} } @Override
public String serialize(List<Book> books) {
// TODO Auto-generated method stub
return null;
} }
Pull解析方式
我最喜欢这种解析方式,它最轻巧,简便。android 用到了很多xml的文件,系统都是用pull来解析的。从这个层面中可以看出来。android建议使用这种解析方式。
PullBookParser.java
package com.example.phonedemo.util; import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.List; import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlSerializer; import android.util.Xml; import com.example.phonedemo.model.Book; public class PullBookParser implements BookParserImpl { @Override
public List<Book> parse(InputStream is) {
// TODO Auto-generated method stub
List<Book> books = null;
Book book = null; XmlPullParser parser = Xml.newPullParser();
try {
parser.setInput(is, "UTF-8");
int eventType = parser.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
switch (eventType) {
case XmlPullParser.START_DOCUMENT:
books = new ArrayList<Book>();
break;
case XmlPullParser.START_TAG:
if (parser.getName().equals("book")) {
book = new Book();
book.setId(Integer.parseInt(parser.getAttributeValue(0)));
} else if (parser.getName().equals("name")) {
parser.next();
book.setName(parser.getText());
} else if (parser.getName().equals("price")) {
parser.next();
book.setPrice(Float.parseFloat(parser.getText()));
}
break;
case XmlPullParser.END_TAG:
if (parser.getName().endsWith("book")) {
books.add(book);
book = null;
}
break;
}
parser.next();
eventType = parser.getEventType();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return books;
} @Override
public String serialize(List<Book> books) {
// TODO Auto-generated method stub
XmlSerializer serializer = Xml.newSerializer();
StringWriter writer = new StringWriter();
try {
serializer.setOutput(writer);
serializer.startDocument("UTF-8", true);
serializer.startTag("", "books");
for (Book book : books) {
serializer.startTag("", "book");
serializer.attribute("", "id", String.valueOf(book.getId())); serializer.startTag("", "name");
serializer.text(book.getName());
serializer.endTag("", "name"); serializer.startTag("", "price");
serializer.text(book.getPrice() + "");
serializer.endTag("", "price");
serializer.endTag("", "book");
}
serializer.endTag("", "books");
serializer.endDocument();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("doc: " + writer.toString());
return writer.toString();
}
}
最后,附上Activity
package com.example.phonedemo; import java.io.InputStream;
import java.util.ArrayList;
import java.util.List; import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient; import android.app.Activity;
import android.content.Context;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.Button;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast; import com.example.phonedemo.model.Book;
import com.example.phonedemo.util.DomBookParser;
import com.example.phonedemo.util.PullBookParser;
import com.example.phonedemo.util.SaxBookParser; public class XMLParserDemo extends Activity { private static final String TAG = "XMLParserDemo"; private static final String PATH = "http://192.168.1.121:8080/wwwroot/android/book.html"; private List<Book> list = null;
private Button dom = null;
private Button sax = null;
private Button pull = null;
private Button clear = null;
private TextView parser = null;
private ListView listView = null; /**
* 异步请求数据
*
* @author qinxijuan
*
*/
private class MyAsyncTask extends AsyncTask<String, Integer, InputStream> { // 表示当前使用哪一种解析方式,0:dom ; 1: sax; 2:pull
private int flag = 0; public MyAsyncTask(int flag) {
this.flag = flag;
} @Override
protected void onPostExecute(InputStream result) {
if (result != null) {
if (flag == 0) {
domParserFromInputStream(result);
} else if (flag == 1) {
saxParserFromInputStream(result);
} else if (flag == 2) {
pullParserFromInputStream(result);
}
} else {
Toast.makeText(XMLParserDemo.this, "数据获取失败!",
Toast.LENGTH_SHORT).show();
}
} @Override
protected void onPreExecute() {
Log.i(TAG, "onPreExecute() Loading ... ");
} @Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
} @Override
protected InputStream doInBackground(String... params) { InputStream result = null;
HttpClient client = new DefaultHttpClient();
HttpGet get = new HttpGet(params[0]);
HttpResponse response = null;
try {
response = client.execute(get);
if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
HttpEntity entity = response.getEntity();
result = entity.getContent();
}
} catch (Exception e) {
e.printStackTrace();
} return result;
} } static class ViewHolder {
TextView id;
TextView name;
TextView price;
} class MyBaseAdapter extends BaseAdapter { private List<Book> list = null;
private LayoutInflater ly = null; public MyBaseAdapter(Context context, List<Book> list) {
this.ly = LayoutInflater.from(context);
this.list = list;
} @Override
public int getCount() {
// TODO Auto-generated method stub
return this.list.size();
} @Override
public Object getItem(int arg0) {
// TODO Auto-generated method stub
return null;
} @Override
public long getItemId(int arg0) {
// TODO Auto-generated method stub
return 0;
} @Override
public View getView(int position, View convertView, ViewGroup arg2) {
ViewHolder viewHolder = null;
if (convertView == null) {
viewHolder = new ViewHolder();
convertView = ly.inflate(R.layout.simpleitem, null);
viewHolder.id = (TextView) convertView.findViewById(R.id.id);
viewHolder.name = (TextView) convertView
.findViewById(R.id.name);
viewHolder.price = (TextView) convertView
.findViewById(R.id.age);
convertView.setTag(viewHolder);
} else {
viewHolder = (ViewHolder) convertView.getTag();
}
viewHolder.id.setText(String.valueOf(list.get(position).getId()));
viewHolder.name.setText(list.get(position).getName());
viewHolder.price.setText(String.valueOf(list.get(position)
.getPrice()));
return convertView;
} } @Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
super.setContentView(R.layout.xml_parser_layout); this.dom = (Button) super.findViewById(R.id.dom);
this.sax = (Button) super.findViewById(R.id.sax);
this.pull = (Button) super.findViewById(R.id.pull);
this.clear = (Button) super.findViewById(R.id.clear);
this.parser = (TextView) super.findViewById(R.id.parser);
this.listView = (ListView) super.findViewById(R.id.list_view); this.clear.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// TODO Auto-generated method stub
list = new ArrayList<Book>();
MyBaseAdapter adapter = new MyBaseAdapter(XMLParserDemo.this,
list);
listView.setAdapter(adapter);
parser.setText("数据清除完毕");
}
}); this.dom.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
// TODO Auto-generated method stub
MyAsyncTask mTask = new MyAsyncTask(0);
mTask.execute(PATH);
parser.setText("使用dom方式解析");
}
}); this.sax.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
MyAsyncTask mTask = new MyAsyncTask(1);
mTask.execute(PATH);
parser.setText("使用sax方式解析");
}
}); this.pull.setOnClickListener(new OnClickListener() { @Override
public void onClick(View arg0) {
// TODO Auto-generated method stub
MyAsyncTask mTask = new MyAsyncTask(2);
mTask.execute(PATH);
parser.setText("使用pull方式解析");
}
});
} public void domParserFromInputStream(InputStream input) {
list = new ArrayList<Book>();
DomBookParser domParser = new DomBookParser();
System.out.println("input: " + input.toString());
list = domParser.parse(input);
MyBaseAdapter adapter = new MyBaseAdapter(this, list);
this.listView.setAdapter(adapter);
} public void saxParserFromInputStream(InputStream input) {
list = new ArrayList<Book>();
SaxBookParser saxParser = new SaxBookParser();
list = saxParser.parse(input);
MyBaseAdapter adapter = new MyBaseAdapter(this, list);
this.listView.setAdapter(adapter);
} public void pullParserFromInputStream(InputStream input) {
PullBookParser pullParser = new PullBookParser();
list = pullParser.parse(input);
MyBaseAdapter adapter = new MyBaseAdapter(this, list);
this.listView.setAdapter(adapter);
} }
xml_parser_layout.xml
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <Button
android:id="@+id/dom"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Dom" /> <Button
android:id="@+id/sax"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Sax" /> <Button
android:id="@+id/pull"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="pull" /> <Button
android:id="@+id/clear"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="clear" />
</LinearLayout> <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" > <TextView
android:id="@+id/parser"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text=" " />
</LinearLayout> <LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content" > <ListView
android:id="@+id/list_view"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout> </LinearLayout>
Android 通过Dom, Sax, Pull解析网络xml数据的更多相关文章
- - XML 解析 总结 DOM SAX PULL MD
目录 目录 XML 解析 总结 DOM SAX PULL MD 几种解析方式简介 要解析的内容 DOM 解析 代码 输出 SAX 解析 代码 输出 JDOM 解析 代码 输出 DOM4J 解析 代码 ...
- Android开发8——利用pull解析器读写XML文件
一.基本介绍 对XML解析有SAX和DOM等多种方式,Android中极力推荐xmlpull方式解析xml.xmlpull不仅可用在Android上同样也适用于javase,但在javase环境中需自 ...
- [Swift通天遁地]四、网络和线程-(5)解析网络请求数据:String(字符串)、Data(二进制数据)和JSON数据
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- Android SAX、DOM、Pull解析xml文件剖析与案例讲解
XML介绍 XML(Extensible Markup Language) 即可扩展标记语言,与HTML一样,都是SGML(Standard Generalized Markup Language,标 ...
- Android学习笔记_7_使用 sax 或者 dom 或者 pull 解析XML文件
一.Pull解析介绍: Android上使用SAX和DOM方式解析XML的方法,并且对两种做了简单的比较,通过比较我们知道对在往往内存比较稀缺的移动设备上运行的Android系统来说,SAX是一种比较 ...
- Java sax、dom、pull解析xml
-------------------------------------SAX解析xml---------------------------------- >Sax定义 SAX是一个解析速度 ...
- 解析XML:DOM,SAX,PULL
Android解析XML有三种方式:DOM(document object model).SAX(simple api XML).PULL 1.DOM DOM解析XML文件时,会将XML文件的所有内容 ...
- 黎活明8天快速掌握android视频教程--15_采用Pull解析器解析和生成XML内容
1.该项目主要有下面的两个作用 (1)将xml文件解析成对象的List对象,xml文件可以来自手机本地,也可以来自服务器返回的xml数据 (2)强list对象保存成xml文件,xml保存到手机的内存卡 ...
- SAX PULL解析实例
XML三种解析方式: SAX解析:基于事件驱动,事件机制基于回调函数的,得到节点和节点之间内容时也会回调事件 PULL解析:相同基于事件驱动,仅仅只是回调时是常量 DOM解析:是先把XML文件装入内存 ...
随机推荐
- spring mvc框架 遇到的问题
web.xml配置文件代码: <?xml version="1.0" encoding="UTF-8"?> <web-app version= ...
- nginx gzip on
# Gzip settings. gzip on; gzip_http_version 1.0;默认值是1.1 gzip_comp_level ; #压缩级别,1压缩比最小处理速度最快,9压缩比最大但 ...
- JavaScriptの例
Dateのオブジェクト: <html> <head> <title>Date Object Example</title> </head> ...
- svn添加强制注释,pre-commit结合python
鉴于组内有些人在提交代码的时候并不写注释,而且没有固定格式,所以准备给svn提交时增加强制注释. 首先找到代码库里的hooks目录,正常建svn库的时候都有这个目录.进入hooks目录,找到pre-c ...
- 【LeetCode题意分析&解答】34. Search for a Range
Given a sorted array of integers, find the starting and ending position of a given target value. You ...
- JavaScript 的 Promise
先看这个 http://www.html5rocks.com/zh/tutorials/es6/promises/#toc-api [JavaScript Promise 浏览器支持的Promise ...
- java核心技术学习笔记之一程序设计环境
一术语 JDK:Java Delelpment Jit JRE:Java Runtime Environment 二.安装jdk1.8.0_25 设置环境变量(建议直接安装在C盘下),使用:隔开 C: ...
- .NET(C#):使用XPath查询带有命名空间(有xmlns)的XML
原文http://www.cnblogs.com/mgen/archive/2011/05/24/2056025.html 众所周知,XmlDocument可以进行XPath查询,但实际上这里所说的X ...
- java.lang.RuntimeException: Unable to start activity ComponentInfo
异常:java.lang.RuntimeException: Unable to start activity ComponentInfo{com.william/com.william.Result ...
- 【方法2】删除Map中Value反复的记录,而且仅仅保留Key最小的那条记录
依据guigui111111的建议:先把Map按Key从大到小排序,然后再把Key和Value互换.这也是一种非常好的思路,我写了一下代码,顺便贴上来,供大家參考与分享. package shuai. ...