前言
在上一篇博客已经介绍了Android解析XML的几种方式,分别有:SAX、DOM、PULL。详细的可以看看上一篇博客:http://www.cnblogs.com/plokmju/p/android_XMLForSAX.html。这篇博客就介绍一下PULL解析XML。
XMLPULL的一些特点:
- 简单的接口:XMLPULL由一个接口(XmlPullParser)、一个例外(XmlPullParserException)、一个工厂(XmlPullParserFactory)来创建。
- 易用性:只有一个关键的next()方法,用于检索下一事件。
- 易扩展:使用通用的接口,并允许多个实现功能,具有更好的扩展性。
- 性能:XMLPULL被设计为允许执行速度非常快的XML解析器。
- 内存要求低:XMLPULL被设计为兼容J2ME,在小型设备上,解析XML时占用非常小的内存。
关键方法next()
对于XMLPULL,只有一个关键的next()方法需要了解一下,它是用于检索下一个事件,并有五个事件,这五个分别是:
- START_DOCUMENT:文档的开始,解析器尚未读取任何输入。
- START_TAG:开始标签的解析。
- TEXT:标签内元素的内容解析。
- END_TAG:结束标签的解析。
- END_DOCUMENT:文档的结束。
虽然说关键方法只有一个用于检索下一事件的方法next(),但是还存在一些方法也可以检索下一事件,用于不同的情况下使用,如:nextText():用于检索下一元素的文本;nextTag():用于检索下一元素的标签。
XMLPULL的简单步骤
- 需要建立一个XMLPULL解析器对象。通过XmlPullParserFactory对象得到解析器对象XmlPullParser。
- 再使用XmlPullParser.setInput()方法设置解析器的输入。
- 之后再通过判断事件类型,循环调用next()方法获得解析的数据。
对于XmlPullParserFactory类,没有提供公开的构造方法(单例模式),必须使用它的静态方法newInstance()来获得对象实例。获得XmlPullParser必须使用XmlPullParserFactory.newPullParser()获得。
示例
现在通过一个示例程序来讲解一下XMLPULL的使用。
这是一个Android应用程序,需要增加访问网络的权限,解析IIS服务器上的一个静态的.XML文件。布局界面也比较简单,就是一个按钮,这里不展示代码了,具体的可以下载代码查看。
待解析的XML文件内容:
<?xml version="1.0" encoding="utf-8"?> <persons> <person id="23"> <name >Jack</name> <age>21</age> </person> <person id="20"> <name>Dick</name> <age>23</age> </person> </persons>
IIS服务器上的XML文件,使用的HTTPURLConnection的方式获得,具体参见另外一篇博客:http://www.cnblogs.com/plokmju/p/java-HTTP.html。这里就再重复给出。
新建一个Person类,用于存放通过XML解析之后的数据,只有三个字段id、name、age并提供对于的get()set()方法,还有toString()方法,这里不展示代码了。
以下是PullXML的解析类:
1 package cn.bgxt.parser; 2 3 import java.io.IOException; 4 import java.io.InputStream; 5 import java.util.ArrayList; 6 import java.util.List; 7 8 import org.xmlpull.v1.XmlPullParser; 9 import org.xmlpull.v1.XmlPullParserException; 10 import org.xmlpull.v1.XmlPullParserFactory; 11 12 import cn.pull.domain.Person; 13 14 public class PullXMLTools { 15 16 public PullXMLTools() { 17 // TODO Auto-generated constructor stub 18 } 19 20 /** 21 * 把服务器传递过的XML流数据解析成对象 22 * @param inputStream XML流 23 * @param encode 编码格式 24 * @return 25 */ 26 public static List<Person> parserXML(InputStream inputStream, String encode) 27 throws XmlPullParserException, IOException { 28 List<Person> list = null; 29 Person person = null; 30 //获得一个XMLPULL工厂类的实例 31 XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); 32 //获得一个XML解析器的实例 33 XmlPullParser parser = factory.newPullParser(); 34 //设置解析器的输入,使用inputStream流式数据。 35 parser.setInput(inputStream, encode); 36 //判断当前的事件类型 37 int eventType = parser.getEventType(); 38 //循环读取,知道事件类型为文档结束 39 while (eventType != XmlPullParser.END_DOCUMENT) { 40 switch (eventType) { 41 // 通过判断事件类型来选择执行不同的代码 42 case XmlPullParser.START_DOCUMENT: 43 //文档开始的时候,实例化list对象,用于存放XML解析后的数据 44 list=new ArrayList<Person>(); 45 break; 46 case XmlPullParser.START_TAG: 47 //读取标签的时候触发这个事件 48 if(parser.getName().equals("person")) 49 { 50 //如果当前读取到的节点是person节点,那么实例化一个person对象。 51 person=new Person(); 52 //获得person节点中的属性ID 53 int id=Integer.parseInt(parser.getAttributeValue(0)); 54 person.setId(id); 55 } 56 else if(parser.getName().equals("name")) 57 { 58 if(person!=null) 59 { 60 //获得name节点的下一个element Text 61 String name=parser.nextText(); 62 person.setName(name); 63 } 64 } 65 else if(parser.getName().equals("age")) 66 { 67 if(person!=null) 68 { 69 //获得age节点的下一个element Text 70 int age=Integer.parseInt(parser.nextText()); 71 person.setAge(age); 72 } 73 } 74 break; 75 case XmlPullParser.END_TAG: 76 if(parser.getName().equals("person")) 77 { 78 //读到结束节点标签,如果为person,则把之前读取到的person对象加入list中, 79 //并且制空person对象。 80 list.add(person); 81 person=null; 82 } 83 break; 84 } 85 //读取 86 eventType=parser.next(); 87 } 88 return list; 89 } 90 91 }
Activity中的代码,需要实现一个按钮的点击事件,因为是在Android4.0+的环境下,需要使用多线程访问网络。
1 package cn.bgxt.xmlforpull; 2 3 import java.io.InputStream; 4 import java.util.List; 5 import cn.bgxt.Http.HttpUtils; 6 import cn.bgxt.parser.PullXMLTools; 7 import cn.pull.domain.Person; 8 import android.os.Bundle; 9 import android.app.Activity; 10 import android.view.Menu; 11 import android.view.View; 12 import android.widget.Button; 13 14 public class MainActivity extends Activity { 15 16 private Button btn; 17 18 @Override 19 protected void onCreate(Bundle savedInstanceState) { 20 super.onCreate(savedInstanceState); 21 setContentView(R.layout.activity_main); 22 23 btn=(Button)findViewById(R.id.btn); 24 25 btn.setOnClickListener(new View.OnClickListener() { 26 27 @Override 28 public void onClick(View v) { 29 // TODO Auto-generated method stub 30 Thread thread=new Thread(new Runnable() { 31 @Override 32 public void run() { 33 String path="http://192.168.1.107:1231/persons.xml"; 34 InputStream inputStream=HttpUtils.getXML(path); 35 List<Person> list=null; 36 try { 37 list = PullXMLTools.parserXML(inputStream, "utf-8"); 38 for(Person person:list) 39 { 40 System.out.println(person.toString()); 41 } 42 } catch (Exception e) { 43 // TODO: handle exception 44 } 45 46 } 47 }); 48 thread.start(); 49 } 50 }); 51 } 52 53 }
在设备上运行程序,如果读取成功,可以在LogCat中查看到输出内容。
提供一下示例程序的源码,有需要的朋友可以下载观看:http://download.csdn.net/detail/plokmju88/5640375
总结
现在已经说了两种在Android平台下解析XML的方式,分别是SAX和PULL,这两种方式都适用于Android平台,因为都是以流的形式访问数据,消耗的硬件资源小,速度快,但是也存在不同的适用环境。如果清楚的知道XML文档的结构,每一级节点的名称,那么使用PULL方式可以简化开发,但是如果不确定XML文档的结构,那还是使用SAX的方式比较妥当,无需关心各节点的名称。
请支持原创,尊重原创,转载请注明出处。谢谢。