本文实例讲述了使用sax来解析xml。通常来说在android里面可以使用sax和dom,dom需要把整个xml文件读入内存再解析,比较消耗内存,而sax是基于事件驱动的处理方式,可以在各节点触发回调函数,不过sax适合节点结构简单的xml文档,复杂的xml文档在后期的节点深度处理会有点麻烦。
本文要解析的test.xml文件如下:
1
2
3
4
5
6
7
8
|
<?xml version= "1.0" encoding= "utf-8" ?> <test> <title>testsax</title> <content aa= "1" bb= "2" > <name>hellogv</name> <url>http: //blog.csdn.net/hellogv</url> </content> </test> |
解析如上xml的结果如下图所示:
使用sax解析,需要定义saxparserfactory(使应用程序能够配置和获取基于 sax 的解析器以解析 xml 文档),saxparser(从各种输入源解析 xml),xmlreader(使用回调函数读取 xml 文档),其中xmlreader是个关键。xmlreader可以为解析xml定义各种回调函数,“条件符合”的时候触发这些回调函数。
1
2
3
4
5
6
|
saxparserfactory factory = saxparserfactory.newinstance(); saxparser parser = factory.newsaxparser(); xmlreader reader = parser.getxmlreader(); reader.setcontenthandler(handler); reader.parse( new inputsource(testsax. this .getresources() .openrawresource(r.raw.test))); |
在这段代码里,xmlreader就调用继承defaulthandler的saxhandler。defaulthandler已实现contenthandler, dtdhandler, entityresolver, errorhandler等接口,包含常见读取xml的操作,具体请看下面的saxhandler.java源码。
最终生成xml的结果如下图所示:
上图是读取各节点之后,使用xmlserializer重新组合并输出xml字符串。
本文的main.xml代码如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
<?xml version= "1.0" encoding= "utf-8" ?> <linearlayout xmlns:android= "http://schemas.android.com/apk/res/android" android:orientation= "vertical" android:layout_width= "fill_parent" android:layout_height= "fill_parent" > <button android:layout_height= "wrap_content" android:layout_width= "fill_parent" android:id= "@+id/btnsax" android:text= "使用sax解析xml" ></button> <button android:layout_height= "wrap_content" android:layout_width= "fill_parent" android:text= "生成xml" android:id= "@+id/btnoutput" ></button> <edittext android:text= "@+id/edittext01" android:id= "@+id/edittext01" android:layout_width= "fill_parent" android:layout_height= "fill_parent" ></edittext> </linearlayout> |
saxhandler.java的源码如下:
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
|
package com.testsax; import java.util.arraylist; import org.xml.sax.attributes; import org.xml.sax.saxexception; import org.xml.sax.helpers.defaulthandler; import android.util.log; public class saxhandler extends defaulthandler{ private arraylist<string> keys = new arraylist<string>(); //保存字段名称 private arraylist<object> values = new arraylist<object>(); //保存值 @override public void startdocument() throws saxexception { super .startdocument(); } @override public void enddocument() throws saxexception { super .enddocument(); } @override public void startelement(string uri, string localname, string qname, attributes attributes) throws saxexception { //保存开始标记 keys.add( "starttag" ); values.add(localname); log.e( "starttag" ,localname); //保存属性值 for ( int i = 0 ; i < attributes.getlength(); i++ ){ keys.add( "attr" ); string[] str= new string[ 2 ]; str[ 0 ]=attributes.getlocalname(i); str[ 1 ]=attributes.getvalue(i); values.add(str); log.e( "attr" ,str[ 0 ]+ "=" +str[ 1 ]); } } @override public void endelement(string uri, string localname, string qname) throws saxexception { //保存结束标记 keys.add( "endtag" ); values.add(localname); log.e( "endtag" ,localname); } @override public void characters( char [] ch, int start, int length) throws saxexception { string value = new string(ch, start, length); value = value.trim(); if (value.length() == 0 ) return ; keys.add( "text" ); values.add(value); log.e( "text" ,value); } public arraylist<string> getkeys() { return keys; } public arraylist<object> getvalues() { return values; } } |
testsax.java的源码如下:
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
|
package com.testsax; import java.io.stringwriter; import javax.xml.parsers.saxparser; import javax.xml.parsers.saxparserfactory; import org.xml.sax.inputsource; import org.xml.sax.xmlreader; import org.xmlpull.v1.xmlserializer; import android.app.activity; import android.os.bundle; import android.util.xml; import android.view.view; import android.widget.button; import android.widget.edittext; public class testsax extends activity { /** called when the activity is first created. */ button btnsax, btnoutput; edittext memo; saxhandler handler = new saxhandler(); @override public void oncreate(bundle savedinstancestate) { super .oncreate(savedinstancestate); setcontentview(r.layout.main); btnsax = (button) this .findviewbyid(r.id.btnsax); btnsax.setonclicklistener( new clickevent()); btnoutput = (button) this .findviewbyid(r.id.btnoutput); btnoutput.setonclicklistener( new clickevent()); memo = (edittext) this .findviewbyid(r.id.edittext01); } class clickevent implements view.onclicklistener { @override public void onclick(view v) { if (v == btnsax) { //解析xml,并保存标记,属性等值 try { saxparserfactory factory = saxparserfactory.newinstance(); saxparser parser = factory.newsaxparser(); xmlreader reader = parser.getxmlreader(); reader.setcontenthandler(handler); reader.parse( new inputsource(testsax. this .getresources() .openrawresource(r.raw.test))); } catch (exception ee) {} } else if (v == btnoutput) { //生成xml try { xmlserializer serializer = xml.newserializer(); stringwriter writer = new stringwriter(); try { serializer.setoutput(writer); serializer.startdocument( "utf-8" , true ); for ( int i= 0 ;i<handler.getkeys().size();i++) { if (handler.getkeys().get(i).equals( "starttag" )) { serializer.starttag( "" , (string) handler.getvalues().get(i)); } else if (handler.getkeys().get(i).equals( "attr" )){ string[] str= (string[]) handler.getvalues().get(i); serializer.attribute( "" ,str[ 0 ],str[ 1 ]); } else if (handler.getkeys().get(i).equals( "text" )) serializer.text((string)handler.getvalues().get(i)); else if (handler.getkeys().get(i).equals( "endtag" )) { serializer.endtag( "" , (string) handler.getvalues().get(i)); } } serializer.enddocument(); string text=writer.tostring(); text=text.replace( "><" , ">/r/n<" ); memo.settext(text); //输出到文本框 } catch (exception e) { throw new runtimeexception(e); } } catch (exception e) {} } } } } |
感兴趣的读者可以自己动手调试运行一下本实例代码,希望能对大家的android项目开发起到参考借鉴作用。