android html 解析我想解析XML数据到listView中,

下图的xml怎么解析并把数据放到listview里_百度知道Android-搭建简单服务端+ListView异步加载数据
Android-搭建简单服务端+ListView异步加载数据日 本篇博文带给大家的是教大家如何在MyEclipse中搭建一个服务端,并通过手机端与其通信,异步加载数据。 笔者使用的是MyEclipse,各位也可以直接用Eclipse创建Java Web项目,谷歌提供的ADT Bundle是不能创建Web项目,读者可以下载Eclipse For JaveEE Developer这个IDE。 下面来介绍如何在MyEclipse创建一个Web项目,并部署到Tomcat当中,关于Tomcat的配置笔者在这里就不多说了。
创建一个名为Test的Web项目,项目结构如下图所示:
我创建了一个images文件夹和list.xml文件,images文件夹存放的是一些图片,是我们下面要获取的,list.xml是一个xml文件,内容如下:
我们可以看到list.xml最外层是一个contacts标签,里面有多个子contact标签,每个子标签包含id、name和image内容,这就是我们下面要解析的内容对应每一个Contact对象。这里要提一下,我们看到image标签,src是图片url地址,这个地址是我PC的IP地址,读者在测试的时候需要将这个IP地址改为你的PC的IP地址,如何得到?运行->cmd->ipconfig /all查看ipv4地址,就是你电脑的ip地址了。创建好Web项目之后,我们在电脑上测试一下,在浏览器输入地址:http://192.192.8.233:8080/Test/list.xml看到以上内容,说明我们已经可以访问到我们的服务端了,下面我们就可以开发我们的客户端:我这里创建了一个07_DataAsyncLoad的项目:目录结构如下:因为需要联网,在AndroidManifest.xml设置权限:
根据服务端list.xml,我们需要定义一个实体类:/07_DataAsyncLoad/src/com/wwj/domain/Contact.javapackage com.wwj.
* 联系人实体类
* @author wwj
public class Contact {
public Contact(int id, String name, String image) {
this.name =
this.image =
public Contact() {
需要访问服务端并且解析xml文件,我们定义一个服务类:/07_DataAsyncLoad/src/com/wwj/service/ContactService.javapackage com.wwj.
import java.io.F
import java.io.FileOutputS
import java.io.InputS
import java.net.HttpURLC
import java.net.URL;
import java.util.ArrayL
import java.util.L
import org.xmlpull.v1.XmlPullP
import com.wwj.domain.C
import com.wwj.utils.MD5;
import android.net.U
import android.util.X
public class ContactService {
* 获取联系人
public static List getContacts() throws Exception{
// 服务器文件路径
String path = "http://192.192.8.233:8080/Test/list.xml";
HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
conn.setConnectTimeout(5000); //设置超时5秒
conn.setRequestMethod("GET"); //设置请求方式
if(conn.getResponseCode() == 200){ //连接成功返回码200
return parseXML(conn.getInputStream());
* 利用pull解析器对xml文件进行解析
* @param xml
* @throws Exception
private static List parseXML(InputStream xml) throws Exception{
List contacts = new ArrayList();
Contact contact =
XmlPullParser pullParser = Xml.newPullParser();
pullParser.setInput(xml, "UTF-8");
int event = pullParser.getEventType(); //取得开始文档语法
while(event != XmlPullParser.END_DOCUMENT){
//只要不等于文档结束事件,循环解析
switch (event) {
case XmlPullParser.START_TAG:
//开始标签
if("contact".equals(pullParser.getName())){
contact = new Contact();
contact.id = new Integer(pullParser.getAttributeValue(0));
}else if("name".equals(pullParser.getName())){
contact.name = pullParser.nextText(); //取得后面节点的文本值
}else if("image".equals(pullParser.getName())){
contact.image = pullParser.getAttributeValue(0); //取得第一个属性的值
case XmlPullParser.END_TAG:
//结束标签
if("contact".equals(pullParser.getName())){
contacts.add(contact); //将contact对象添加到集合中
event = pullParser.next(); //去下一个标签
* 获取网络图片,如果图片存在于缓存中,就返回该图片,否则从网络中加载该图片并缓存起来
* @param path 图片路径
public static Uri getImage(String path, File cacheDir) throws Exception{// path -> MD5 ->32字符串.jpg
File localFile = new File(cacheDir, MD5.getMD5(path)+ path.substring(path.lastIndexOf(".")));
if(localFile.exists()){
return Uri.fromFile(localFile);
HttpURLConnection conn = (HttpURLConnection) new URL(path).openConnection();
conn.setConnectTimeout(5000);
conn.setRequestMethod("GET");
if(conn.getResponseCode() == 200){
FileOutputStream outStream = new FileOutputStream(localFile);
InputStream inputStream = conn.getInputStream();
byte[] buffer = new byte[1024];
int len = 0;
while( (len = inputStream.read(buffer)) != -1){
outStream.write(buffer, 0, len);
inputStream.close();
outStream.close();
return Uri.fromFile(localFile);
上面代码已经很清楚的定义了获取服务端数据的方法,大致流程是这样的:传递一个网络路径path,通过URL打开连接,通过HttpURLConnection连接服务端,得到输入流,解析xml文件再获得数据。上面代码获取网络图片,需要进行MD5加密计算,具体方法如下:/07_DataAsyncLoad/src/com/wwj/utils/MD5.javapackage com.wwj.
import java.security.MessageD
import java.security.NoSuchAlgorithmE
public class MD5 {
* MD5加密算法
* @param content
public static String getMD5(String content) {
MessageDigest digest = MessageDigest.getInstance("MD5");
digest.update(content.getBytes());
return getHashString(digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
* 获得哈希字符串
* @param digest
private static String getHashString(MessageDigest digest) {
StringBuilder builder = new StringBuilder();
for (byte b : digest.digest()) {
builder.append(Integer.toHexString((b >> 4) & 0xf));
builder.append(Integer.toHexString(b & 0xf));
return builder.toString();
好,这样我们的服务类就已经写完了,这时我们在MainActivity进行异步加载数据:/07_DataAsyncLoad/src/com/wwj/asyntask/MainActivity.javapackage com.wwj.
import java.io.F
import java.util.L
import com.wwj.adapter.ContactA
import com.wwj.asyntask.R;
import com.wwj.domain.C
import com.wwj.service.ContactS
import android.app.A
import android.os.B
import android.os.E
import android.os.H
import android.os.M
import android.widget.ListV
public class MainActivity extends Activity {
ListView listV
F // 缓存文件
Handler handler = new Handler() {
public void handleMessage(Message msg) {
listView.setAdapter(new ContactAdapter(MainActivity.this,
(List) msg.obj, R.layout.listview_item, cache));
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
listView = (ListView) this.findViewById(R.id.listView);
cache = new File(Environment.getExternalStorageDirectory(), "cache"); // 实例化缓存文件
if (!cache.exists())
cache.mkdirs(); // 如果文件不存在,创建
// 开一个线程来加载数据
new Thread(new Runnable() {
public void run() {
List data = ContactService.getContacts();
// 通过handler来发送消息
handler.sendMessage(handler.obtainMessage(22, data));
} catch (Exception e) {
e.printStackTrace();
}).start();
protected void onDestroy() {
// 删除缓存
for (File file : cache.listFiles()) {
file.delete();
cache.delete();
super.onDestroy();
}这里我们开了一个线程来加载数据,是因为网络操作不能在UI线程中进行,加载完数据后通过Hanlder发送消息,显示列表。一般情况下,我们获取图片需要另外处理,我们有很多种方法,最常用的就是Handler+Thread和AsyncTask两种,具体实现来看:/07_DataAsyncLoad/src/com/wwj/adapter/ContactAdapter.java我们定义了一个列表适配器,用来填充我们的数据,我们的图片异步加载也在这里实现了:package com.wwj.
import java.io.F
import java.util.L
import android.content.C
import android.net.U
import android.os.AsyncT
import android.view.LayoutI
import android.view.V
import android.view.ViewG
import android.widget.BaseA
import android.widget.ImageV
import android.widget.TextV
import com.wwj.asyntask.R;
import com.wwj.domain.C
import com.wwj.service.ContactS
* 自定义适配器
* @author wwj
public class ContactAdapter extends BaseAdapter {
private List // 缓存数据
private int listviewI // 条目id
private F // 缓存文件
LayoutInflater layoutI
public ContactAdapter(Context context, List data,
int listviewItem, File cache) {
this.data =
this.listviewItem = listviewI
this.cache =
layoutInflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);// 获取布局填充服务
* 得到数据的总数
public int getCount() {
return data.size();
* 根据数据索引得到集合所对应的数据
public Object getItem(int position) {
return data.get(position);
public long getItemId(int position) {
* 当listView每显示一个条目的时候,都会调用这个方法
public View getView(int position, View convertView, ViewGroup parent) {
ImageView imageView =
TextView textView =
if (convertView == null) {
convertView = layoutInflater.inflate(listviewItem, null); // 获取条目的view对象
imageView = (ImageView) convertView.findViewById(R.id.imageView);
textView = (TextView) convertView.findViewById(R.id.textView);
convertView.setTag(new DataWrapper(imageView, textView));
DataWrapper dataWrapper = (DataWrapper) convertView.getTag();
imageView = dataWrapper.imageV
textView = dataWrapper.textV
Contact contact = data.get(position);
textView.setText(contact.name);
asyncImageLoad(imageView, contact.image);
return convertV
private void asyncImageLoad(ImageView imageView, String path) {
AsyncImageTask asyncImageTask = new AsyncImageTask(imageView);
asyncImageTask.execute(path);
* 使用AsyncTask异步加载图片
* @author Administrator
private final class AsyncImageTask extends AsyncTask {
private ImageView imageV
public AsyncImageTask(ImageView imageView) {
this.imageView = imageV
protected Uri doInBackground(String... params) {// 子线程中执行的
return ContactService.getImage(params[0], cache);
} catch (Exception e) {
e.printStackTrace();
protected void onPostExecute(Uri result) {// 运行在主线程
if (result != null && imageView != null)
imageView.setImageURI(result);
// 使用Handler进行异步加载图片
* private void asyncImageLoad(final ImageView imageView, final String path)
final Handler handler = new Handler(){
public void
handleMessage(Message msg) {//运行在主线程中
Uri uri = (Uri)msg.
if(uri!=null && imageView!= null) imageView.setImageURI(uri);
* Runnable runnable = new Runnable() {
public void run() {
ContactService.getImage(path, cache);
handler.sendMessage(handler.obtainMessage(10, uri));
} catch (Exception e) {
e.printStackTrace();
new Thread(runnable).start();
private final class DataWrapper {
public ImageView imageV
public TextView textV
public DataWrapper(ImageView imageView, TextView textView) {
this.imageView = imageV
this.textView = textV
以上就是本项目所有的代码,运行项目效果如下:最后附上服务端和客户端源码:http://download.csdn.net/detail/wwj_748/7300567
(window.slotbydup=window.slotbydup || []).push({
id: '2467140',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467141',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467143',
container: s,
size: '1000,90',
display: 'inlay-fix'
(window.slotbydup=window.slotbydup || []).push({
id: '2467148',
container: s,
size: '1000,90',
display: 'inlay-fix'安卓开发之去服务器取数据并展示到ListView上的小案例
第一步:搭建TomCat服务器和准备数据。数据为3张图片和fruit.xml文件。
第二步:去服务器取数据。
new&Thread(new&Runnable() {
@Overridepublic void&run() {
String path =&"http://本机IP地址:8080/fruit.xml";URL url =&new&URL(path);HttpURLConnection conn = (HttpURLConnection) url.openConnection();conn.setRequestMethod("GET");conn.setConnectTimeout(5000);int&code = conn.getResponseCode();if&(code ==&200) {
InputStream in = conn.getInputStream();//返回的流为xml文件,此处写解析xml文件的逻辑。}
}&catch&(Exception e) {
e.printStackTrace();}
}).start();
第三步:解析xml文件,新建XmlParserUtils类和News类,根据xml文件内容写News类。
public static List parserXml(InputStream in) throws XmlPullParserException, IOException {
List newsList =
News news =
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlPullParser parser = factory.newPullParser();
//设置解析内容
parser.setInput(in, "utf-8");
//获取事件的返回类型
int type = parser.getEventType();
//开始解析
while (type != XmlPullParser.END_DOCUMENT) {
switch (type) {
case XmlPullParser.START_TAG:
if ("Items".equals(parser.getName())) {
newsList = new ArrayList();
} else if ("fruit".equals(parser.getName())) {
news = new News();
} else if ("image".equals(parser.getName())) {
news.setImage(parser.nextText());
} else if ("name".equals(parser.getName())) {
news.setName(parser.nextText());
} else if ("detils".equals(parser.getName())) {
news.setDetils(parser.nextText());
} else if ("comment".equals(parser.getName())) {
news.setComment(parser.nextText());
case XmlPullParser.END_TAG:
if ("fruit".equals(parser.getName())) {
newsList.add(news);
type = parser.next();
return newsList;}
第四步:新建MyImageView类继承ImageView,写接收url就能显示图片的方法
public class MyImageView extends ImageView {
private Handler handler = new Handler(){
public void handleMessage(Message msg) {
super.handleMessage(msg);
Bitmap bitmap = (Bitmap) msg.obj;
MyImageView.this.setImageBitmap(bitmap);//此处是重点
public MyImageView(Context context) {
super(context);
public MyImageView(Context context, AttributeSet attrs) {
super(context, attrs);
public MyImageView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
public void setImageUrl(final String path){
new Thread(new Runnable() {
public void run() {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(<span STYLE="color:#);
int code = conn.getResponseCode();
if (code==<span STYLE="color:#){
InputStream in = conn.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(in);
Message msg = Message.obtain();
msg.obj = bitmap;
handler.sendMessage(msg);
} catch (Exception e) {
e.printStackTrace();
}).start();
第五步:新建itemlayout.xml写ListView的列表项布局,使用自定义ImageView时要加上完整包名
已投稿到:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。Android应用开发(20)
转载请注明出处:
& & & &今天我们来学习另一种非常重要的数据交换&#26684;式-XML。XML(Extensible Markup Language的缩写,意为可扩展的标记语言),它是一种元标记语言,即定义了用于定义其他特定领域有关语义的、结构化的标记语言,这些标记语言将文档分成许多部件并对这些部件加以标识。XML 文档定义方式有:文档类型定义(DTD)和XML Schema。DTD定义了文档的整体结构以及文档的语法,应用广泛并有丰富工具支持。XML
Schema用于定义管理信息等更强大、更丰富的特征。XML能够更精确地声明内容,方便跨越多种平台的更有意义的搜索结果。它提供了一种描述结构数据的&#26684;式,简化了网络中数据交换和表示,使得代码、数据和表示分离,并作为数据交换的标准&#26684;式,因此它常被称为智能数据文档。
& & & 由于XML具有很强的扩展性,致使它需要很强的基础规则来支持扩展,所以在编写XML文件时,我们应该严&#26684;遵守XML的语法规则,一般XML语法有如下规则:(1)起始和结束的标签相匹配;(2)嵌套标签不能相互嵌套;(3)区分大小写。下面是给出了一个编写错误的XML文件以及对其的错误说明,如下:
本文只是对XML做了个简单的介绍,要想学习更多有关XML知识,可以访问如下网站:。
XML在实际应用中比较广泛,Android也不例外,作为承载数据的重要角色,如何读写XML称为Android开发中一项重要的技能。
Android中XML数据解析使用实例
& & & &在Android开发中,较为常用的XML解析器有SAX解析器、DOM解析器和PULL解析器,下面我们将会一一学习如何使用这些XML解析器。那在介绍这几种XML解析器过程中,我们依然是要通过一个实例来学习它们的实际开发方法,下面是我们Demo实例的程序列表清单,如下:
& & & & &图1-1 客户端 & & & & & & & & & & & & & & & & & & & & &图1-2 服务器端
来整理下我们实现的Demo实例思路:客户端通过网络请求读取服务器端的person.xml,person.xml文件中的内容如下:
&?xml version=&1.0& encoding=&UTF-8&?&
&person id=&1&&
&name&Transformers First&/name&
&height&7&/height&
&imageurl&imagefile/transformers_one.png&/imageurl&
&person id=&2&&
&name&Transformers second&/name&
&height&4&/height&
&imageurl&imagefile/transformers_two.png&/imageurl&
&person id=&3&&
&name&Transformers third&/name&
&height&8.5&/height&
&imageurl&imagefile/transformers_three.png&/imageurl&
&person id=&4&&
&name&Transformers fourth&/name&
&height&14.5&/height&
&imageurl&imagefile/transformers_four.png&/imageurl&
&person id=&5&&
&name&Transformers fifth&/name&
&height&27.5&/height&
&imageurl&imagefile/transformers_five.png&/imageurl&
&person id=&6&&
&name&Transformers Sixth&/name&
&height&8.5&/height&
&imageurl&imagefile/transformers_six.png&/imageurl&
&person id=&7&&
&name&Transformers Seventh&/name&
&height&5&/height&
&imageurl&imagefile/transformers_seven.png&/imageurl&
&person id=&8&&
&name&Transformers Eighth&/name&
&height&12.5&/height&
&imageurl&imagefile/transformers_eight.png&/imageurl&
&/persons&
接着将获取到的person.xml的文件流信息分别使用SAX、DOM和PULL解析方式解析成Java对象,然后将解析后获取到的Java对象信息以列表的形式展现在客户端,思路很简单吧。
Demo实例工程的下载地址:
好了,基本了解了Demo实例的整体思路后,接下来我们将学习如何具体实现它们。
SAX解析XML文件实例
& & & &SAX(Simple For XML)是一种基于事件的解析器,它的核心是事件处理模式,它主要是围绕事件源和事件处理器来工作的。当事件源产生事件后,会调用事件处理器中相应的方法来处理一个事件,那在事件源调用对应的方法时也会向对应的事件传递一些状态信息,以便我们根据其状态信息来决定自己的行为。
& & & 接下来我们将具体地学习一下SAX解析工作的主要原理:在读取XML文档内容时,事件源顺序地对文档进行扫描,当扫描到文档的开始与结束(Document)标签、节点元素的开始与结束(Element)标签时,直接调用对应的方法,并将状态信息以参数的形式传递到方法中,然后我们可以依据状态信息来执行相关的自定义操作。为了更好的理解SAX解析的工作原理,我们结合具体的代码来更深入的理解下,代码如下:
* SAX解析类
* @author AndroidLeaf
public class MyHandler extends DefaultHandler {
//当开始读取文档标签时调用该方法
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
//当开始读取节点元素标签时调用该方法
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
super.startElement(uri, localName, qName, attributes);
//do something
//当读取节点元素的子类信息时调用该方法
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
super.characters(ch, start, length);
//do something
//当结束读取节点元素标签时调用该方法
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, qName);
//do something
//当结束读取文档标签时调用该方法
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
//do something
首先我们先认识一个重要的类--DefaultHandler,该类是XML解析接口(EntityResolver, DTDHandler, ContentHandler, ErrorHandler)的缺省实现,在通常情况下,为应用程序扩展DefaultHandler并覆盖相关的方法要比直接实现这些接口更容易。接着重写startDocument(),startElement(),characters(),endElement和endDocument()五个方法,这些方法会在事件源(在org.xml.sax包中的XMLReader,通过parser()产生事件)读取到不同的XML标签所产生事件时调用。那我们开发时只要在这些方法中实现我们的自定义操作即可。下面总结罗列了一些使用SAX解析时常用的接口、类和方法:
事件处理器名称
事件处理器处理的事件
ContentHandler
XML文档的开始与结束;
XML文档节点元素的开始与结束,接收字符数据,跳过实体,接收元素内容中可忽略的空白等。
DTDHandler
处理DTD解析时产生的相应事件
ErrorHandler
处理XML文档时产生的错误
EntityResolver
处理外部实体
startDocument()
用于处理文档解析开始时间
startElement(String uri,String localName,String qName
&Attributes attributes)
处理元素开始时间,从参数中可以获取元素所在空间的URL,元素名称,属性列表等信息。
characters(char[] ch,int start,int length)
处理元素的字符内容,从参数中可以获得内容
endElement(String uri,String localName,String qName)
处理元素结束时间,从参数中可以获取元素所在空间的URL,元素名称等信息。
endDocument()
用于处理文档解析的结束事件
基本了解完SAX解析工作原理及开发时用到的常用接口和类后,接下来我们来学习一下使用SAX解析XML的编程步骤,一般分为5个步骤,如下:
1、获取创建一个SAX解析工厂实例;
2、调用工厂实例中的newSAXParser()方法创建SAXParser解析对象;
3、实例化CustomHandler(DefaultHandler的子类);
4、连接事件源对象XMLReader到事件处理类DefaultHandler中;
5、通过DefaultHandler返回我们需要的数据集合。
接着,我们按照这5个步骤来完成Demo实例解析person.xml的工作(person.xml的内容上面已经列出),解析的关键代码是在Demo实例工程中的XmlTools类中,具体代码如下:
/**--------------SAX解析XML-------------------*/
* @param mInputStream 需要解析的person.xml的文件流对象
* @param nodeName 节点名称
* @return mList Person对象集合
public static ArrayList&Person& saxAnalysis(InputStream mInputStream,String nodeName){
//1、获取创建一个SAX解析工厂实例
SAXParserFactory mSaxParserFactory = SAXParserFactory.newInstance();
//2、调用工厂实例中的newSAXParser()方法创建SAXParser解析对象
SAXParser mSaxParser = mSaxParserFactory.newSAXParser();
//3、实例化CustomHandler(DefaultHandler的子类)
CustomHandler mHandler = new CustomHandler(nodeName);
* 4、连接事件源对象XMLReader到事件处理类DefaultHandler中
* 查看parse(InputStream is, DefaultHandler dh)方法源码如下:
* public void parse(InputSource is, DefaultHandler dh)
throws SAXException, IOException {
if (is == null) {
throw new IllegalArgumentException(&InputSource cannot be null&);
// 获取事件源XMLReader,并通过相应事件处理器注册方法setXXXX()来完成的与ContentHander、DTDHander、ErrorHandler,
// 以及EntityResolver这4个接口的连接。
XMLReader reader = this.getXMLReader();
if (dh != null) {
reader.setContentHandler(dh);
reader.setEntityResolver(dh);
reader.setErrorHandler(dh);
reader.setDTDHandler(dh);
reader.parse(is);
mSaxParser.parse(mInputStream, mHandler);
//5、通过DefaultHandler返回我们需要的数据集合
return mHandler.getList();
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}事件处理器类CustomerHandler中的具体代码如下:
* SAX解析类
* @author AndroidLeaf
public class CustomHandler extends DefaultHandler {
//装载所有解析完成的内容
List&HashMap&String, String&& mListMaps =
//装载解析单个person节点的内容
HashMap&String, String& map =
//节点名称
private String nodeN
//当前解析的节点标记
private String currentT
//当前解析的节点值
private String currentV
public ArrayList&Person& getList(){
ArrayList&Person& mList = new ArrayList&Person&();
if(mListMaps != null && mListMaps.size() & 0){
for(int i = 0;i & mListMaps.size();i++){
Person mPerson = new Person();
HashMap&String, String& mHashMap = mListMaps.get(i);
mPerson.setId(Integer.parseInt(mHashMap.get(&id&)));
mPerson.setUserName(mHashMap.get(&name&));
mPerson.setHeight(Float.parseFloat(mHashMap.get(&height&)));
mPerson.setImageUrl(mHashMap.get(&imageurl&));
mList.add(mPerson);
public CustomHandler(String nodeName){
this.nodeName = nodeN
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
mListMaps = new ArrayList&HashMap&String, String&&();
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
if (qName.equals(nodeName)) {
map = new HashMap&String, String&();
if (map != null && attributes != null) {
for (int i = 0; i & attributes.getLength(); i++) {
map.put(attributes.getQName(i), attributes.getValue(i));
// 当前的解析的节点名称
currentTag = qN
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
if (map != null && currentTag != null) {
currentValue = new String(ch, start, length);
if (currentValue != null && !currentValue.equals(&&)
&& !currentValue.equals(&\n&)) {
map.put(currentTag, currentValue);
currentTag =
currentValue =
super.characters(ch, start, length);
public void endElement(String uri, String localName, String qName)
throws SAXException {
// TODO Auto-generated method stub
if (qName.equals(nodeName)) {
mListMaps.add(map);
super.endElement(uri, localName, qName);
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
CustomerHandler通过不断接收事件源传递过来的事件,进而执行相关解析工作并调用对应的方法,然后以参数的形式接收解析结果。为了更好的让读者理解CustomerHandler的解析过程,下面有一张展示解析person.xml文件的流程图,如下:
DOM解析XML文件实例
& & & &DOM是基于树形结构的的节点或信息片段的集合,允许开发人员使用DOM API遍历XML树、检索所需数据。分析该结构通常需要加载整个文档和构造树形结构,然后才可以检索和更新节点信息。Android完全支持DOM 解析。利用DOM中的对象,可以对XML文档进行读取、搜索、修改、添加和删除等操作。
& & & DOM的工作原理:使用DOM对XML文件进行操作时,首先要解析文件,将文件分为独立的元素、属性和注释等,然后以节点树的形式在内存中对XML文件进行表示,就可以通过节点树访问文档的内容,并根据需要修改文档——这就是DOM的工作原理。DOM实现时首先为XML文档的解析定义一组接口,解析器读入整个文档,然后构造一个驻留内存的树结构,这样代码就可以使用DOM接口来操作整个树结构。由于DOM在内存中以树形结构存放,因此检索和更新效率会更高。但是对于特别大的文档,解析和加载整个文档将会很耗资源。 当然,如果XML文件的内容比较小,采用DOM是可行的。下面罗列了一些使用DOM解析时常用的接口和类,如下:
接口或类名称
接口或类说明
该接口定义分析并创建DOM文档的一系列方法,它是文档树的根,是操作DOM的基础。&
该接口继承Node接口,提供了获取、修改XML元素名字和属性的方法
该接口提供处理并获取节点和子节点&#20540;的方法
提供获得子节点个数和当前节点的方法。这样就可以迭代地访问各个节点
该类是Apache的Xerces中的DOM解析器类,可直接解析XML。
接下来我们学习一下使用DOM解析XML的编程步骤,一般分为6个步骤,如下:
1、创建文档对象工厂实例;
2、调用DocumentBuilderFactory中的newDocumentBuilder()方法创建文档对象构造器;
3、将文件流解析成XML文档对象;
4、使用mDocument文档对象得到文档根节点;
5、根据名称获取根节点中的子节点列表;
6 、获取子节点列表中需要读取的节点信息。
然后,我们按照这6个步骤来完成Demo实例解析person.xml的工作(person.xml的内容上面已经列出),解析的关键代码是在Demo实例工程中的XmlTools类中,具体代码如下:
/**--------------DOM解析XML-------------------*/
* @param mInputStream 需要解析的person.xml的文件流对象
* @return mList Person对象集合
public static ArrayList&Person& domAnalysis(InputStream mInputStream){
ArrayList&Person& mList = new ArrayList&Person&();
//1、创建文档对象工厂实例
DocumentBuilderFactory mDocumentBuilderFactory = DocumentBuilderFactory.newInstance();
//2、调用DocumentBuilderFactory中的newDocumentBuilder()方法创建文档对象构造器
DocumentBuilder mDocumentBuilder = mDocumentBuilderFactory.newDocumentBuilder();
//3、将文件流解析成XML文档对象
Document mDocument = mDocumentBuilder.parse(mInputStream);
//4、使用mDocument文档对象得到文档根节点
Element mElement = mDocument.getDocumentElement();
//5、根据名称获取根节点中的子节点列表
NodeList mNodeList =
mElement.getElementsByTagName(&person&);
//6 、获取子节点列表中需要读取的节点信息
for(int i = 0 ;i & mNodeList.getLength();i++){
Person mPerson = new Person();
Element personElement = (Element) mNodeList.item(i);
//获取person节点中的属性
if(personElement.hasAttributes()){
mPerson.setId(Integer.parseInt(personElement.getAttribute(&id&)));
if(personElement.hasChildNodes()){
//获取person节点的子节点列表
NodeList mNodeList2 = personElement.getChildNodes();
//遍历子节点列表并赋值
for(int j = 0;j & mNodeList2.getLength();j++){
Node mNodeChild = mNodeList2.item(j);
if(mNodeChild.getNodeType() == Node.ELEMENT_NODE){
if(&name&.equals(mNodeChild.getNodeName())){
mPerson.setUserName(mNodeChild.getFirstChild().getNodeValue());
}else if(&height&.equals(mNodeChild.getNodeName())){
mPerson.setHeight(Float.parseFloat(mNodeChild.getFirstChild().getNodeValue()));
}else if(&imageurl&.equals(mNodeChild.getNodeName())){
mPerson.setImageUrl(mNodeChild.getFirstChild().getNodeValue());
mList.add(mPerson);
} catch (ParserConfigurationException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SAXException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
PULL解析XML文件实例
& & & &PULL的解析方式与SAX解析类&#20284;,都是基于事件的模式。不同的是,在PULL解析过程中返回的是数字,且我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码。PULL 的工作原理:XML pull提供了开始元素和结束元素。当某个元素开始时,我们可以调用parser.nextText从XML文档中提取所有字符数据。当解释到一个文档结束时,自动生成EndDocument事件。下面罗列了一些使用PULL解析时常用的接口、类和方法:
接口和类名称
接口和类说明
XmlPullParser
XML Pull解析接口,该接口定义了解析功能
XmlSerializer
它是一个接口,定义了XML信息集的序列
XmlPullParserFactory
XML PULL解析工厂类,用于创建XML Pull解析器
XmlPullParserException
抛出单一的XML pull解析器相关的错误
getEventType()
该方法用于获取当前解析到的事件类型
nextText()
提取当前节点元素的字符数据
获取下一个节点元素的类型
获取当前节点元素的名称
getAttributeCount()
获取当前节点属性的数量
XmlPullParser.START_DOCUMENT
文档开始解析类型
XmlPullParser.END_DOCUMENT
文档结束解析类型
XmlPullParser.START_TAG
节点开始解析类型
XmlPullParser.END_TAG
节点结束解析类型
XmlPullParser.TEXT
文本解析类型
接下来我们将学习使用PULL解析XML的编程步骤,一般分为5个步骤,如下:
1、获取PULL解析工厂实例对象;
2、使用XmlPullParserFactory的newPullParser()方法实例化PULL解析实例对象;
3、设置需解析的XML文件流和字符编码;
4、获取事件解析类型;
5、循环遍历解析,当文档解析结束时结束循环;
然后,我们按照这5个步骤来完成Demo实例解析person.xml的工作(person.xml的内容上面已经列出),解析的关键代码是在Demo实例工程中的XmlTools类中,具体代码如下:
/**--------------PULL解析XML-------------------*/
* @param mInputStream 需要解析的person.xml的文件流对象
* @param encode 设置字符编码
* @return mList Person对象集合
public static ArrayList&Person& PullAnalysis(InputStream mInputStream,String encode){
ArrayList&Person& mList =
Person mPerson =
//1、获取PULL解析工厂实例对象
XmlPullParserFactory mXmlPullParserFactory = XmlPullParserFactory.newInstance();
//2、使用XmlPullParserFactory的newPullParser()方法实例化PULL解析实例对象
XmlPullParser mXmlPullParser = mXmlPullParserFactory.newPullParser();
//3、设置需解析的XML文件流和字符编码
mXmlPullParser.setInput(mInputStream, encode);
//4、获取事件解析类型
int eventType = mXmlPullParser.getEventType();
//5、循环遍历解析,当文档解析结束时结束循环
while(eventType != XmlPullParser.END_DOCUMENT){
switch (eventType) {
//开始解析文档
case XmlPullParser.START_DOCUMENT:
mList = new ArrayList&Person&();
//开始解析节点
case XmlPullParser.START_TAG:
if(&person&.equals(mXmlPullParser.getName())){
mPerson = new Person();
//获取该节点中的属性的数量
int attributeNumber = mXmlPullParser.getAttributeCount();
if(attributeNumber & 0){
//获取属性值
mPerson.setId(Integer.parseInt(mXmlPullParser.getAttributeValue(0)));
}else if(&name&.equals(mXmlPullParser.getName())){
//获取该节点的内容
mPerson.setUserName(mXmlPullParser.nextText());
}else if(&height&.equals(mXmlPullParser.getName())){
mPerson.setHeight(Float.parseFloat(mXmlPullParser.nextText()));
}else if(&imageurl&.equals(mXmlPullParser.getName())){
mPerson.setImageUrl(mXmlPullParser.nextText());
//解析节点结束
case XmlPullParser.END_TAG:
if(&person&.equals(mXmlPullParser.getName())){
mList.add(mPerson);
eventType = mXmlPullParser.next();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
现在我么已经分别使用SAX、DOM和PULL解析器解析person.xml的文件流后,结果返回Person对象的集合,我们的解析工作便完成了,接下来需要做的就是将解析结果以列表的方式展现在客户端界面上。那首先我们先来实现一下从网络服务端获取数据的网络访问代码,在工程中主要包含HttpRequest和MyAsynctask两个类,前者主要功能是执行网络请求,后者是进行异步请求的帮助类。首先看HttpRequest类的代码,如下:
* 网络访问类
* @author AndroidLeaf
public class HttpRequest {
* @param urlStr 请求的Url
* @return InputStream 返回请求的流数据
public static InputStream getInputStreamFromNetWork(String urlStr)
URL mUrl =
HttpURLConnection
mConnection=
InputStream mInputStream =
mUrl = new URL(urlStr);
mConnection = (HttpURLConnection)mUrl.openConnection();
mConnection.setDoOutput(true);
mConnection.setDoInput(true);
mConnection.setReadTimeout(15 * 1000);
mConnection.setConnectTimeout(15 * 1000);
mConnection.setRequestMethod(&GET&);
int responseCode = mConnection.getResponseCode();
if(responseCode == HttpURLConnection.HTTP_OK){
//获取下载资源的大小
//contentLength = mConnection.getContentLength();
mInputStream = mConnection.getInputStream();
return mInputS
} catch (IOException e) {
// TODO: handle exception
* 得到图片字节流 数组大小
public static byte[] readStream(InputStream mInputStream){
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] buffer = new byte[2048];
int len = 0;
while((len = mInputStream.read(buffer)) != -1){
outStream.write(buffer, 0, len);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
if(outStream != null){
outStream.close();
if(mInputStream != null){
mInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return outStream.toByteArray();
}接着实现MyAsynctask类的代码,如下:
* 异步请求工具类
* @author AndroidLeaf
public class MyAsynctask extends AsyncTask&Object, Void, Object&
private ImageView mImageV
private ImageCallBack mImageCallB
//请求类型,分为XML文件请求和图片下载请求
private int typeId;
//使用的XML解析类型ID
private int requestId;
* 定义一个回调,用于监听网络请求,当请求结束,返回访问结果
public HttpDownloadedListener mHttpDownloadedL
public interface HttpDownloadedListener{
public void onDownloaded(String result,int requestId);
public void setOnHttpDownloadedListener(HttpDownloadedListener mHttpDownloadedListener){
this.mHttpDownloadedListener = mHttpDownloadedL
public MyAsynctask(ImageView mImageView,ImageCallBack mImageCallBack,int requestId){
this.mImageView = mImageV
this.mImageCallBack = mImageCallB
this.requestId = requestId;
protected void onPreExecute() {
// TODO Auto-generated method stub
super.onPreExecute();
protected Object doInBackground(Object... params) {
// TODO Auto-generated method stub
InputStream mInputStream = HttpRequest.getInputStreamFromNetWork((String)params[0]);
if(mInputStream != null){
switch ((int)params[1]) {
case Constants.TYPE_STR:
typeId = Constants.TYPE_STR;
return WriteIntoFile(mInputStream);
case Constants.TYPE_STREAM:
typeId = Constants.TYPE_STREAM;
return getBitmap(HttpRequest.readStream(mInputStream),
200, 200);
protected void onPostExecute(Object result) {
// TODO Auto-generated method stub
if(result != null){
switch (typeId) {
case Constants.TYPE_STR:
mHttpDownloadedListener.onDownloaded((String)result,requestId);
case Constants.TYPE_STREAM:
mImageCallBack.resultImage(mImageView,(Bitmap)result);
typeId = -1;
super.onPostExecute(result);
public Bitmap getBitmap(byte[] bytes,int width,int height){
//获取屏幕的宽和高
* 为了计算缩放的比例,我们需要获取整个图片的尺寸,而不是图片
* BitmapFactory.Options类中有一个布尔型变量inJustDecodeBounds,将其设置为true
* 这样,我们获取到的就是图片的尺寸,而不用加载图片了。
* 当我们设置这个值的时候,我们接着就可以从BitmapFactory.Options的outWidth和outHeight中获取到值
BitmapFactory.Options op = new BitmapFactory.Options();
op.inJustDecodeBounds =
Bitmap pic = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
int wRatio = (int) Math.ceil(op.outWidth / (float) width); //计算宽度比例
int hRatio = (int) Math.ceil(op.outHeight / (float) height); //计算高度比例
* 接下来,我们就需要判断是否需要缩放以及到底对宽还是高进行缩放。
* 如果高和宽不是全都超出了屏幕,那么无需缩放。
* 如果高和宽都超出了屏幕大小,则如何选择缩放呢》
* 这需要判断wRatio和hRatio的大小
* 大的一个将被缩放,因为缩放大的时,小的应该自动进行同比率缩放。
* 缩放使用的还是inSampleSize变量
if (wRatio & 1 && hRatio & 1) {
if (wRatio & hRatio) {
op.inSampleSize = wR
op.inSampleSize = hR
op.inJustDecodeBounds = //注意这里,一定要设置为false,因为上面我们将其设置为true来获取图片尺寸了
pic = BitmapFactory.decodeByteArray(bytes, 0, bytes.length);
* 将下载的XML文件流存储到手机指定的SDcard目录下
* @param mInputStream 需要读入的流
* @return String 返回存储的XML文件的路径
public String WriteIntoFile(InputStream mInputStream){
if(isSDcard()){
FileOutputStream mOutputStream = new FileOutputStream(new File(getFileName()));
int len = -1;
byte[] bytes = new byte[2048];
while((len = mInputStream.read(bytes)) != -1){
mOutputStream.write(bytes, 0, len);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
if(mOutputStream != null){
mOutputStream.close();
if(mInputStream != null){
mInputStream.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
return getFileName();
* 检测SDcard是否可用
public boolean isSDcard(){
if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
* 获取需要存储的XML文件的路径
* @return String 路径
public String getFileName(){
String path = Environment.getExternalStorageDirectory().getPath() +&/XMLFiles&;
File mFile = new File(path);
if(!mFile.exists()){
mFile.mkdirs();
return mFile.getPath() + &/xmlfile.xml&;
}实现完网络请求的功能后,我们就可以从服务端获取到person.xml的文件流,然后再分别用SAX、DOM和PULL解析器将文件流解析(在上面介绍这几种解析器时已经实现了解析的代码,在工程中的XmlTools类中)成对应的Java对象集合,最后将Java对象集合以列表的形式展现在客户端界面上,那接下来我们将实现该功能。在工程中主要包含MainActivity、MyAdapter和ImageCallBack类,首先实现MainActivity的代码,如下:
public class MainActivity extends ListActivity implements HttpDownloadedListener{
private ProgressDialog mProgressD
//需要解析的节点名称
private String nodeName = &person&;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_list);
//初始化数据
initData();
public void initData(){
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mProgressDialog.setTitle(&正在加载中.....&);
mProgressDialog.show();
//首次进入界面是,默认使用SAX解析数据
downloadData(this,Constants.XML_PATH,Constants.REQUEST_PULL_TYPE,null,null,Constants.TYPE_STR);
public boolean onCreateOptionsMenu(Menu menu) {
// TOdO Auto-generated method stub
getMenuInflater().inflate(R.menu.main, menu);
public boolean onOptionsItemSelected(MenuItem item) {
// TOdO Auto-generated method stub
int requestId = -1;
switch (item.getItemId()) {
case R.id.sax:
requestId = Constants.REQUEST_SAX_TYPE;
case R.id.dom:
requestId = Constants.REQUEST_DOM_TYPE;
case R.id.pull:
requestId = Constants.REQUEST_PULL_TYPE;
downloadData(this, Constants.XML_PATH, requestId, null, null, Constants.TYPE_STR);
mProgressDialog.show();
return super.onOptionsItemSelected(item);
public void onDownloaded(String result,int requestId) {
// TODO Auto-generated method stub
FileInputStream mFileInputStream =
mFileInputStream = new FileInputStream(new File(result));
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
ArrayList&Person& mList =
switch (requestId) {
case Constants.REQUEST_SAX_TYPE:
mList = XmlTools.saxAnalysis(mFileInputStream,nodeName);
case Constants.REQUEST_DOM_TYPE:
mList = XmlTools.domAnalysis(mFileInputStream);
case Constants.REQUEST_PULL_TYPE:
mList = XmlTools.PullAnalysis(mFileInputStream,&UTF-8&);
MyAdapter myAdapter = new MyAdapter(this, mList);
setListAdapter(myAdapter);
if(mProgressDialog.isShowing()){
mProgressDialog.dismiss();
//执行网络下载代码
public static void downloadData(HttpDownloadedListener mDownloadedListener,String url,int requestId,ImageView mImageView,ImageCallBack mImageCallBack,int typeId){
MyAsynctask mAsynctask = new MyAsynctask(mImageView,mImageCallBack,requestId);
mAsynctask.setOnHttpDownloadedListener(mDownloadedListener);
mAsynctask.execute(url,typeId);
}然后再实现界面的适配器类--MyAdapter,具体代码如下:
* 数据界面展示的适配器类
* @author AndroidLeaf
public class MyAdapter extends BaseAdapter {
private Context mC
private ArrayList&Person& mL
private Bitmap[] mB
public MyAdapter(Context mContext,ArrayList&Person& mList){
this.mContext = mC
this.mList = mL
mBitmaps = new Bitmap[mList.size()];
public int getCount() {
// TODO Auto-generated method stub
return mList.size();
public Object getItem(int position) {
// TODO Auto-generated method stub
return mList.get(position);
public long getItemId(int position) {
// TODO Auto-generated method stub
public View getView(int position, View convertView, ViewGroup parent) {
// TODO Auto-generated method stub
ViewHolder mH
Person mPerson = mList.get(position);
if(convertView == null){
convertView = LayoutInflater.from(mContext).inflate(R.layout.item_list, null);
mHolder = new ViewHolder();
mHolder.mTextView_id = (TextView)convertView.findViewById(R.id.item_id);
mHolder.mTextView_name = (TextView)convertView.findViewById(R.id.item_name);
mHolder.mTextView_height = (TextView)convertView.findViewById(R.id.item_height);
mHolder.mImageView_image = (ImageView)convertView.findViewById(R.id.item_image);
//为Imageview设置TAG,作为每一个ImageView的唯一标识
mHolder.mImageView_image.setTag(mPerson.getImageUrl());
convertView.setTag(mHolder);
mHolder = (ViewHolder)convertView.getTag();
mHolder.mTextView_id.setText(String.valueOf(mPerson.getId()));
mHolder.mTextView_name.setText(mPerson.getUserName());
mHolder.mTextView_height.setText(String.valueOf(mPerson.getHeight()));
* 解决异步加载过程中Listview列表中图片显示错位问题
//判断当前位置的ImageView和是否为上次执行加载操作的ImageView,若false则重置上次加载的那个Imageview中的图片资源
if(!mPerson.getImageUrl().equals(String.valueOf(mHolder.mImageView_image.getTag()))){
mHolder.mImageView_image.setImageResource(R.drawable.ic_launcher);
//重新为ImageView实例设置TAG
mHolder.mImageView_image.setTag(mPerson.getImageUrl());
if(mBitmaps[position] == null){
//执行异步加载图片操作
MainActivity.downloadData((HttpDownloadedListener)mContext, Constants.BASE_PATH + mPerson.getImageUrl(), -1,
mHolder.mImageView_image, new MyImageCallBack(position,mPerson.getImageUrl()), Constants.TYPE_STREAM);
mHolder.mImageView_image.setImageBitmap(mBitmaps[position]);
return convertV
class ViewHolder{
TextView mTextView_
TextView mTextView_
TextView mTextView_
ImageView mImageView_
class MyImageCallBack implements ImageCallBack{
int index = -1;
String imageUrl =
public MyImageCallBack(int index,String imageUrl){
this.index =
this.imageUrl = imageU
public void resultImage(ImageView mImageView, Bitmap mBitmap) {
// TODO Auto-generated method stub
//判断当前显示的ImageView的URL是否与需要下载的图片ImageView的URL相同
if(imageUrl.equals(String.valueOf(mImageView.getTag()))){
mBitmaps[index] = mB
mImageView.setImageBitmap(mBitmap);
观察上面的代码,在实现适配器类时,由于我们需要异步下载图片,因此在图片绑定和显示时由于列表项焦点的不断变换和图片数据加载的延迟会导致ListView中的图片显示错位的问题,为了解决该问题,我们采取对ImageView设置TAG来解决了图片错位问题,那要明白其中的原理,就必须对Listview加载item view列表项的实现机制比较清楚,由于该问题不是本文的重点,因此在此不便细讲,有兴趣的读者可以学习本博客的另一篇文章《Android异步加载数据时ListView中图片错位问题解析》,希望对你有所帮助。在实现图片异步加载时,程序中还使用到了一个非常有用的接口--ImageCallBack,该接口主要作用是将异步下载的图片设置到对应的Imageview控件中,该接口的具体代码如下:
public interface ImageCallBack {
public void resultImage(ImageView mImageView,Bitmap mBitmap);
}当然,还有常量Constants类和Entity对象Person类。Constants类的具体的代码:
* 网络请求的Url地址及一些常量
* @author AndroidLeaf
public class Constants {
public static final String BASE_PATH = &http://10.0.2.2:8080/09_Android_XMLServer_Blog/&;
//person.xml网络请求路径
public static final String XML_PATH = BASE_PATH + &xmlfile/person.xml&;
//使用SAX解析的标签类型
public static final int REQUEST_SAX_TYPE = 0;
//使用DOM解析的标签类型
public static final int REQUEST_DOM_TYPE = 1;
//使用PULL解析的标签类型
public static final int REQUEST_PULL_TYPE = 2;
//请求person.xml文件标签
public static final int TYPE_STR = 1;
//请求图片文件标签
public static final int TYPE_STREAM = 2;
}Person类的代码如下:
public class Person {
private String userN
private String imageU
public int getId() {
public void setId(int id) {
public String getUserName() {
return userN
public void setUserName(String userName) {
this.userName = userN
public float getHeight() {
public void setHeight(float height) {
this.height =
public String getImageUrl() {
return imageU
public void setImageUrl(String imageUrl) {
this.imageUrl = imageU
public String toString() {
return &Person [id=& + id + &, userName=& + userName + &, height=&
+ height + &, imageUrl=& + imageUrl + &]&;
}全部的编码都已经完成,最后我们再Android模拟器上运行我们的Demo实例工程,运行及操作的效果图如下:
SAX、DOM和PULL解析器的比较
& & & &SAX解析器的特点:SAX解析器解析速度快、高效,占用内存少。但它的缺点是编码实现比其它解析方式更复杂,对于只需解析较少数量的XML文件时,使用SAX解析显得实现代码比较臃肿。
& & & &DOM解析器的特点:由于DOM在内存中是以树形结构存放的,那虽然检索和更新效率比较高,但对于使用DOM来解析较大数据的XML文件,将会消耗很大内存资源,这对于内存资源比较有限的手机设备来讲,是不太适合的。
& & & &PULL解析器的特点:PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器,Android官方推荐开发者们使用Pull解析技术。Pull解析技术是第三方开发的开源技术,它同样可以应用于JavaSE开发。
& & & &根据上面介绍的这些解析器的特点我们可在不同的开发情况下选择不同的解析方式,比如说,当XML文件数据较小时,可以选择DOM解析,因为它将XML数据以树形结构存放在内存中,在占用不多的内存资源情况下检索和更新效率比较高,当XML文件数据较大时,可以选择SAX和PULL解析,因为它们不需要将所有的XML文件都加载到内存中,这样对有限的Android内存更有效。SAX和PULL解析的不同之处是,PULL解析并不像SAX解析那样监听元素的结束,而是在开始处完成了大部分处理。这有利于提早读取XML文件,可以极大的减少解析时间,这种优化对于连接速度较漫的移动设备而言尤为重要。对于XML文档数据较大但只需要文档的一部分时,XML
PULL解析器则是更为有效的方法。
总结:本文学习了在Android开发中解析XML文件的几种常用解析方式,这几种解析方式各有优缺点,我们应根据不同的开发需求选择合适的解析方式。最后总结一下在Android解析XML所需掌握的主要知识点:(1)XML的特点以及结构组成形式,掌握如何编写XML文件;(2)了解SAX、PULL和DOM解析器的特点,并掌握在Android中使用这三种解析方式的使用;(3)比较三种解析器的特点,学会在不同情况下选择合适的解析方式。
源代码下载,请戳下面:
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:36075次
排名:千里之外
原创:24篇
评论:24条
(1)(10)(13)

我要回帖

更多关于 android html 解析 的文章

 

随机推荐