zoukankan      html  css  js  c++  java
  • 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的解析类: 

     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的方式比较妥当,无需关心各节点的名称。

      请支持原创,尊重原创,转载请注明出处。谢谢。

  • 相关阅读:
    Android零碎知识之Style and Theme
    Java 线程池(一):开篇及Executor整体框架介绍
    ADB命令笔记本
    volatile变量理解 via《Java并发编程实战》
    Java NIO
    乱七八糟(一)
    Android事件分发机制
    AndroidStudio下的依赖管理
    shell--填过的坑
    兼容类问题
  • 原文地址:https://www.cnblogs.com/plokmju/p/android_XMLForPull.html
Copyright © 2011-2022 走看看