_043_Android_解析XML之PULL

前言

  在上一篇博客已经介绍了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的解析类: 

package cn.bgxt.parser;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;

import cn.pull.domain.Person;

public class PullXMLTools {

    public PullXMLTools() {
        // TODO Auto-generated constructor stub
    }

    /**
     * 把服务器传递过的XML流数据解析成对象 
     * @param inputStream  XML流
     * @param encode  编码格式
     * @return
     */
    public static List<Person> parserXML(InputStream inputStream, String encode)
            throws XmlPullParserException, IOException {
        List<Person> list = null;
        Person person = null;
        //获得一个XMLPULL工厂类的实例
        XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
        //获得一个XML解析器的实例
        XmlPullParser parser = factory.newPullParser();
        //设置解析器的输入,使用inputStream流式数据。
        parser.setInput(inputStream, encode);
        //判断当前的事件类型
        int eventType = parser.getEventType();
        //循环读取,知道事件类型为文档结束
        while (eventType != XmlPullParser.END_DOCUMENT) {
            switch (eventType) {
            // 通过判断事件类型来选择执行不同的代码
            case XmlPullParser.START_DOCUMENT:
                //文档开始的时候,实例化list对象,用于存放XML解析后的数据
                list=new ArrayList<Person>();                
                break;
            case XmlPullParser.START_TAG:
                //读取标签的时候触发这个事件
                if(parser.getName().equals("person"))
                {
                    //如果当前读取到的节点是person节点,那么实例化一个person对象。
                    person=new Person();
                    //获得person节点中的属性ID
                    int id=Integer.parseInt(parser.getAttributeValue(0));
                    person.setId(id);
                }
                else if(parser.getName().equals("name"))
                {
                    if(person!=null)
                    {
                        //获得name节点的下一个element Text
                        String name=parser.nextText();
                        person.setName(name);
                    }
                }
                else if(parser.getName().equals("age"))
                {
                    if(person!=null)
                    {
                        //获得age节点的下一个element Text
                        int age=Integer.parseInt(parser.nextText());
                        person.setAge(age);
                    }
                }
                break;
            case XmlPullParser.END_TAG:
                if(parser.getName().equals("person"))
                {
                    //读到结束节点标签,如果为person,则把之前读取到的person对象加入list中,
                    //并且制空person对象。
                    list.add(person);
                    person=null;
                }
                break;
            }
            //读取
            eventType=parser.next();
        }
        return list;
    }

}

官方Demo: 

public class Demo {

	public static void main(String args[]) throws XmlPullParserException, IOException {
		XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
		factory.setNamespaceAware(true);
		XmlPullParser xpp = factory.newPullParser();

		xpp.setInput(new StringReader("<foo>Hello World!<h>dfdfdfdf<h>dfdfdfdf</h></h></foo>"));
		int eventType = xpp.getEventType();
		while (eventType != XmlPullParser.END_DOCUMENT) {
			if (eventType == XmlPullParser.START_DOCUMENT) {
				System.out.println("Start document");
			} else if (eventType == XmlPullParser.START_TAG) {
				System.out.println("Start tag " + xpp.getName());
			} else if (eventType == XmlPullParser.END_TAG) {
				System.out.println("End tag " + xpp.getName());
			} else if (eventType == XmlPullParser.TEXT) {
				System.out.println("Text " + xpp.getText());
			}
			eventType = xpp.next();
		}
		System.out.println("End document");
	}

}

总结

          现在已经说了两种在Android平台下解析XML的方式,分别是SAX和PULL,这两种方式都适用于Android平台,因为都是以流的形式访问数据,消耗的硬件资源小,速度快,但是也存在不同的适用环境。如果清楚的知道XML文档的结构,每一级节点的名称,那么使用PULL方式可以简化开发,但是如果不确定XML文档的结构,那还是使用SAX的方式比较妥当,无需关心各节点的名称。

猜你喜欢

转载自blog.csdn.net/poiuyppp/article/details/83858524