Android提高之XML解析与生成实例详解

时间:2022-04-11 05:55:53

本文实例讲述了使用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的结果如下图所示:

Android提高之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的结果如下图所示:

Android提高之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项目开发起到参考借鉴作用。