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文件装入内存 ...
随机推荐
- C++_基础_类和对象2
内容: (1)构造函数 (2)初始化列表及其必要性 (3)支持自定义类型转换的构造函数 (4)this指针 (5)const对象和成员函数 (6)析构函数 1.构造函数1.1 格式: class 类名 ...
- java之观察者模式
import java.util.Observable; import java.util.Observer; class House extends Observable { private ...
- 四轴飞行器1.2.2 RT-Thread 串口
四轴飞行器1.2.2 RT-Thread 串口 本来是打算说根据RT-Thread的设备管理提供的驱动接口些串口驱动的,但是仔细一看,我去,串口驱动写好了,只需要调用就可以了.下面我们说 ...
- AndroidStudio 使用Hide API
1.反射法 速度慢 2.生成新的android.jar 通常需要隐藏API的地方并不多 不需要整个都编译 而且编译出的framework.jar也不全 缺少java.*和javax.* 所以只把需要的 ...
- NodeJS 从0开始
查看Node 基本配置$ npm config ls -l $npm help install将展开install的help文档 初始化目录 npm init 根据提示完成 将生成package.js ...
- vb.net 操作xml
xml文件: <?xml version="1.0" encoding="gb2312"?> <bookstore> <book ...
- 在 Visual C++ 中开发自定义的绘图控件
本文讨论的重点介于两者 之间 — 公共控件赋予您想要的大部分功能,但控件的外观并不是您想要的.例如,列表视图控件提供在许多视图风格中显示数据列表的方式 — 小图标.大图标.列表和详细列表(报告).然而 ...
- Android导航栏ActionBar的具体分析
尊重原创:http://blog.csdn.net/yuanzeyao/article/details/39378825 关于ActionBar,相信大家并不陌生,可是真正能够熟练使用的也不是许多,这 ...
- 《网络编程》Unix 域套接字
概述 Unix 域套接字是一种client和server在单主机上的 IPC 方法.Unix 域套接字不运行协议处理,不须要加入或删除网络报头,无需验证和,不产生顺序号,无需发送确认报文,比因特网域套 ...
- Unity 通过NGUI 完成单摄像机 制作地图
本次思想主要是通过 Ngui的Scroll View 主要是UIPanel的Clipping属性的Alipha Clip 调节窗口大小,遮蔽地图试地图实现在屏幕的部分显示.此方法的好处是不用担心sha ...