Android 采用PULL来解析XML

本文介绍了在Android移动设备中使用PULL解析器解析XML的原理、接口、运行方式及与SAX、DOM解析技术的对比。通过实际案例展示了如何从资产目录中读取xml文件、解析并显示内容,以及如何将解析后的内容写回本地文件。重点在于阐述PULL解析器在内存资源有限的Android设备上的优势。
摘要由CSDN通过智能技术生成

概述:

PULL解析器小巧轻便,解析速度快,简单易用,非常适合在Android移动设备中使用,Android系统内部在解析各种XML时也是用PULL解析器,Android官方推荐开发者们使用Pull解析技术。Pull解析技术是第三方开发的开源技术,它同样可以应用于JavaSE开发。

PULL 的工作原理:

XML pull提供了开始元素和结束元素。当某个元素开始时,可以调用parsernextTextXML文档中提取所有字符数据。当解析到一个文档结束时,自动生成EndDocument事件。

常用的XML pull的接口和类:

XmlPullParser该解析器是一个在org.xmlpull.v1中定义的解析功能的接口。

XmlSerializer它是一个接口,定义了XML信息集的序列。

XmlPullParserFactory这个类用于在XMPULL V1 API中创建XML Pull解析器。

XmlPullParserException抛出单一的XML pull解析器相关的错误。

PULL解析器的运行方式和SAX类似,都是基于事件的模式。

不同的是,在PULL解析过程中返回的是数字,且我们需要自己获取产生的事件然后做相应的操作,而不像SAX那样由处理器触发一种事件的方法,执行我们的代码:

读取到xml声明返回 START_DOCUMENT; 结束返回 END_DOCUMENT ; 开始标签返回 START_TAG;

结束标签返回 END_TAG; 文本返回 TEXT。

几种解析技术的比较与总结: 
对于Android的移动设备而言,因为设备的资源比较宝贵,内存是有限的,所以我们需要选择适合的技术来解析XML,这样有利于提高访问的速度。

DOM在处理XML文件时,将XML文件解析成树状结构并放入内存中进行处理。当XML文件较小时,我们可以选DOM,因为它简单、直观。

SAX则是以事件作为解析XML文件的模式,它将XML文件转化成一系列的事件,由不同的事件处理器来决定如何处理。XML文件较大时,选择SAX技术是比较合理的。虽然代码量有些大,但是它不需要将所有的XML文件加载到内存中。这样对于有限的Android内存更有效,而且Android提供了一种传统的SAX使用方法以及一个便捷的SAX包装器。 使用AndroidutilXml类,从示例中可以看出,会比使用 SAX来得简单。

XML pull解析并未像SAX解析那样监听元素的结束,而是在开始处完成了大部分处理。这有利于提早读取XML文件,可以极大的减少解析时间,这种优化对于连接速度较漫的移动设备而言尤为重要。对于XML文档较大但只需要文档的一部分时,XML Pull解析器则是更为有效的方法。


开发实例:

在asset定义了books.xml文件,对于它,只要是一份格式良好的xml文档即可,具体内容根据需要定义。

读取XML:从定义好的books.xml文件解析并显示出来;

写入XML:将解析后的内容再写入到本地,这里也保存为名字为books.xml的文件。



例如:books.xml定义如下形式:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<? xml version = "1.0" encoding = "utf-8" ?>
< books >
     < book >
         < id >1001</ id >
         < name >Thinking In Java</ name >
         < price >80.00</ price >
     </ book >
     < book >
         < id >1002</ id >
         < name >Core Java</ name >
         < price >90.00</ price >
     </ book >
     < book >
         < id >1003</ id >
         < name >Hello, Andriod</ name >
         < price >100.00</ price >
     </ book >
</ books >

完整代码:

PULLParserActivity:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
package com.xsjayz.xml;
 
import java.io.FileOutputStream;
import java.io.InputStream;
import java.util.List;
 
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
 
/**
  * PULL解析器,这里只是简单的定义了一个TextView显示解析结果,两个Button操作。
  *
  * @since 2012-08-23
  */
public class PULLParserActivity extends Activity {
     
     private static final String TAG = "XML" ;
     private TextView textView = null ;
     private Button readBtn = null ;
     private Button writeBtn = null ;
 
     private BookParser parser;
     private List<Book> booksList;
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super .onCreate(savedInstanceState);
         setContentView(R.layout.main);
 
         textView = (TextView) findViewById(R.id.txt);
         readBtn = (Button) findViewById(R.id.read_btn);
         writeBtn = (Button) findViewById(R.id.write_btn);
 
         readBtn.setOnClickListener( new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 try {
                     InputStream is = getAssets().open( "books.xml" );
                     parser = new PULLBookParser();
                     booksList = parser.parse(is);
                     
                     for (Book book : booksList) {
                         Log.i(TAG, book.toString());
                     }
 
                     for (Book book : booksList) {
                         textView.setText(textView.getText() + book.toString());
                     }
                 } catch (Exception e) {
                     Log.e(TAG, e.getMessage());
                 }
             }
         });
 
         writeBtn.setOnClickListener( new View.OnClickListener() {
             @Override
             public void onClick(View v) {
                 try {
                     String xmlString = parser.serialize(booksList); // 序列化
                     FileOutputStream fos = openFileOutput( "books.xml" ,
                             Context.MODE_PRIVATE);
                     fos.write(xmlString.getBytes( "UTF-8" ));
                 } catch (Exception e) {
                     Log.e(TAG, e.getMessage());
                 }
             }
         });
     }
}

PULLBookParser:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
package com.xsjayz.xml;
 
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;
 
/**
  * PULL解析器,实现了BookParser接口
  */
public class PULLBookParser implements BookParser {
 
     /**
      * @param is
      * @return booksList
      */
     @Override
     public List<Book> parse(InputStream is) throws Exception {
 
         List<Book> booksList = null ;
         Book book = null ;
 
         // 由android.util.Xml创建一个XmlPullParser实例
         XmlPullParser parser = Xml.newPullParser();
         // 设置输入流 并指明编码方式
         parser.setInput(is, "UTF-8" );
         // 产生第一个事件
         int eventType = parser.getEventType();
 
         while (eventType != XmlPullParser.END_DOCUMENT) {
 
             switch (eventType) {
             // 判断当前事件是否为文档开始事件
             case XmlPullParser.START_DOCUMENT:
                 booksList = new ArrayList<Book>(); // 初始化books集合
                 break ;
 
             // 判断当前事件是否为标签元素开始事件
             case XmlPullParser.START_TAG:
 
                 if (parser.getName().equals( "book" )) { // 判断开始标签元素是否是book
                     book = new Book();
                 } else if (parser.getName().equals( "id" )) {
                     eventType = parser.next();
                     // 得到book标签的属性值,并设置book的id
                     book.setId(Integer.parseInt(parser.getText()));
                 } else if (parser.getName().equals( "name" )) { // 判断开始标签元素是否是book
                     eventType = parser.next();
                     book.setName(parser.getText());
                 } else if (parser.getName().equals( "price" )) { // 判断开始标签元素是否是price
                     eventType = parser.next();
                     book.setPrice(Float.parseFloat(parser.getText()));
                 }
                 break ;
 
             // 判断当前事件是否为标签元素结束事件
             case XmlPullParser.END_TAG:
                 if (parser.getName().equals( "book" )) { // 判断结束标签元素是否是book
                     booksList.add(book); // 将book添加到books集合
                     book = null ;
                 }
                 break ;
             }
             // 进入下一个元素并触发相应事件
             eventType = parser.next();
         }
         return booksList;
     }
 
     /**
      * @param books
      * @return writer.toString()
      */
     @Override
     public String serialize(List<Book> books) throws Exception {
 
         // 由android.util.Xml创建一个XmlSerializer实例
         XmlSerializer serializer = Xml.newSerializer();
         StringWriter writer = new StringWriter();
         // 设置输出方向为writer
         serializer.setOutput(writer);
         serializer.startDocument( "UTF-8" , true );
         serializer.startTag( "" , "books" );
 
         for (Book book : books) {
             serializer.startTag( "" , "book" );
             serializer.attribute( "" , "id" , 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();
 
         return writer.toString();
     }
}

BookParser:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
package com.xsjayz.xml;
 
import java.io.InputStream;
import java.util.List;
 
public interface BookParser {
 
     /**
      * 解析输入流 得到Book对象集合
      *
      * @param is
      * @throws Exception
      */
     public List<Book> parse(InputStream is) throws Exception;
 
     /**
      * 序列化Book对象集合 得到XML形式的字符串
      *
      * @param books
      * @throws Exception
      */
     public String serialize(List<Book> books) throws Exception;
}

Book:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
package com.xsjayz.xml;
 
/**
  * Book的model类,定义了Book的所有状态,访问器和修改器,重写了toString方法
  */
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;
     }
 
     @Override
     public String toString() {
         return "id:" + id + "\nname:" + name + "\nprice:" + price + "\n" ;
     }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值