[转载]Android中XML文件的三种解析方式 – 青春流水指间、 – 博客园.
今天学习了xml文件的三种解析方式,其中包括在学习java时学习的SAX和DOM这两种解析方法。在Android中有一种开源的PULL解析方法,今天我将他们的具体用法和大家分享下。
业务需求:
给定一个xml文件,要求分别用SAX,DOM,PULL三种方法对xml文件进行解析。
运行效果图如下:
下面是具体实现步骤:
首先我们需要一个xml文件,下面是我xml文件的存放位置。
该xml文件中的内容我写的比较简单。仅供实现这个功能。下面是我的xml文件的内容。
persons.xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <persons> 3 <person id="1"> 4 <name>刘备</name> 5 <age>12</age> 6 </person> 7 <person id="2"> 8 <name>刘欢</name> 9 <age>14</age> 10 </person> 11 <person id="3"> 12 <name>李明</name> 13 <age>15</age> 14 </person> 15 </persons>
我们可以看到xml文件中只有一个person对象,所以我们必须定义一个person类。
在Android中为了体现封装性,我们需要将不同功能的代码放在不同的包里。下面是我在实现这个功能时,各个代码存放的位置。
Person.java
1 package cn.yj3g.entity; 2 public class Person { 3 4 private int id; 5 private String name; 6 private int age; 7 public Person(int id, String name, int age) { 8 super(); 9 this.id = id; 10 this.name = name; 11 this.age = age; 12 } 13 public Person() { 14 super(); 15 } 16 public int getId() { 17 return id; 18 } 19 20 public void setId(int id) { 21 this.id = id; 22 } 23 public String getName() { 24 return name; 25 } 26 public void setName(String name) { 27 this.name = name; 28 } 29 public int getAge() { 30 return age; 31 } 32 public void setAge(int age) { 33 this.age = age; 34 } 35 @Override 36 public String toString() { 37 return "Person [id=" + id + ", name=" + name + ", age=" + age + "]"; 38 } 39 }
由于三种解析方法都实现了一个功能,就是对xml文件进行解析,所以在这里我们可以将解析方法定义为一个接口,三种解析方法都实现这个接口。下面是我定义的一个接口
IXmlParseService:
1 package cn.yj3g.service; 2 3 import java.io.InputStream; 4 import java.util.List; 5 import cn.yj3g.entity.Person; 6 //定义一个接口 7 public interface IXmlParseService { 8 //接口中的一个解析方法。如果引用这个接口,就要实现这个方法,这样做更简便,封装性更好。 9 public List<Person> getPersonsByParseXml(InputStream is) throws Exception; 10 }
下来就是具体用三种方式对xml实现解析。下面是三种解析方式的具体代码:
<1>DOM解析 DomParseService:
1 package cn.yj3g.service; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.List; 6 import javax.xml.parsers.DocumentBuilder; 7 import javax.xml.parsers.DocumentBuilderFactory; 8 import org.w3c.dom.Document; 9 import org.w3c.dom.Element; 10 import org.w3c.dom.Node; 11 import org.w3c.dom.NodeList; 12 import cn.yj3g.entity.Person; 13 /** 14 * DOM解析器在解析XML文档时,会把文档中的所有元素,按照其出现的层次关系,解析成一个个Node对象(节点)。Node对象提供了一系列常量来代表结点的类型 15 * ,当开发人员获得某个Node类型后,就可以把Node节点转换成相应节点对象(Node的子类对象),以便于调用其特有的方法。 16 * Node对象提供了相应的方法去获得它的父结点或子结点。编程人员通过这些方法就可以读取整个XML文档的内容、或添加、修改、删除XML文档的内容. 17 * 18 * 缺点: 19 * 一次性的完全加载整个xml文件,需要消耗大量的内存。 20 */ 21 public class DomParseService implements IXmlParseService { 22 23 @Override 24 public List<Person> getPersonsByParseXml(InputStream is) throws Exception { 25 List<Person> list = null; 26 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 27 DocumentBuilder builder = factory.newDocumentBuilder(); 28 Document document = builder.parse(is); 29 // 得到根元素,这里是persons 30 Element root = document.getDocumentElement(); 31 // 得到一个集合,里面存放在xml文件中所有的person 32 NodeList nodeList = root.getElementsByTagName("person"); 33 // 34 if (nodeList == null || nodeList.getLength() == 0) { 35 return null; 36 } 37 // 初始化 38 list = new ArrayList<Person>(); 39 40 for (int i = 0; i < nodeList.getLength(); i++) { 41 // xml中的person标签 42 Element element = (Element) nodeList.item(i); 43 Person p = new Person(); 44 // 得到person的id属性 45 int id = Integer.parseInt(element.getAttribute("id")); 46 p.setId(id); 47 // 得到name 48 String name = getAttrText(element, "name"); 49 p.setName(name); 50 // 得到age 51 String age = getAttrText(element, "age"); 52 p.setAge(new Integer(age)); 53 54 list.add(p); 55 } 56 return list; 57 } 58 59 /** 60 * 获得指定元素的子元素中的文本内容 61 */ 62 public String getAttrText(Element element, String name) { 63 NodeList nodeList2 = element.getChildNodes(); 64 Node node = null; 65 for (int i = 0; i < nodeList2.getLength(); i++) { 66 node = nodeList2.item(i); 67 if (node.getNodeName().equals(name)) { 68 return node.getTextContent(); 69 } 70 } 71 return null; 72 } 73 }
<2>SAX解析 SAXParseService:
package cn.yj3g.service; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.SAXException; import org.xml.sax.helpers.DefaultHandler; import cn.yj3g.entity.Person; /** * 优点:SAX解析允许在读取文档的时候,即对文档进行处理,而不必等到整个文档装载完才会文档进行操作。 * */ public class SAXParseService implements IXmlParseService { public List<Person> getPersonsByParseXml(InputStream is) throws Exception { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); saxHandler handler = new saxHandler(); // parser.parse(is, handler); return handler.getList(); } // 自定义一个handler实现DefaultHandler并 重写它的相关方法 private class saxHandler extends DefaultHandler { String currunt = null; List<Person> list = null; Person p = null; @Override public void startDocument() throws SAXException { list = new ArrayList<Person>(); } @Override public void endDocument() throws SAXException { } // 开始解析元素 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if ("person".equals(localName)) { p = new Person(); p.setId(Integer.parseInt(attributes.getValue("id"))); } else if ("name".equals(localName) || "age".equals(localName)) { currunt = localName; } } // 元素解析结束 @Override public void endElement(String uri, String localName, String qName) throws SAXException { if ("person".equals(localName)) { list.add(p); } else if ("name".equals(localName) || "age".equals(localName)) { currunt = null; } } // 解析文本 @Override public void characters(char[] ch, int start, int length) throws SAXException { String s = new String(ch, start, length); if ("name".equals(currunt)) { p.setName(s); } else if ("age".equals(currunt)) { p.setAge(Integer.parseInt(s)); } } // 返回list public List<Person> getList() { return list; } } }
<3>PULL解析 PullParseService:
package cn.yj3g.service; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserFactory; import cn.yj3g.entity.Person; /** * 优点:不是一次加载,中途可以停止。 * */ public class PullParseService implements IXmlParseService { public List<Person> getPersonsByParseXml(InputStream is) throws Exception { List<Person> list = null; Person p = null; XmlPullParserFactory factory = XmlPullParserFactory.newInstance(); XmlPullParser parser = factory.newPullParser(); //设置输入流 parser.setInput(is, "utf-8"); //parser的几种事件类型 int type = parser.getEventType(); while (type != XmlPullParser.END_DOCUMENT) { // String typename = parser.getName(); switch (type) { //文档开始 -->xml中的persons case XmlPullParser.START_DOCUMENT: list = new ArrayList<Person>(); break; //元素开始 case XmlPullParser.START_TAG: if ("person".equals(typename)) { p = new Person(); p.setId(Integer.parseInt(parser.getAttributeValue(0))); // } else if ("name".equals(typename)) { p.setName(parser.nextText()); // } else if ("age".equals(typename)) { p.setAge(Integer.parseInt(parser.nextText())); } break; //元素结束 case XmlPullParser.END_TAG: if ("person".equals(typename)) { list.add(p); p=null; break; } } //最最重要的一步,pull解析中的特有的方法,解析下一个标签 type = parser.next(); } return list; } }
下来就是在主界面上通过Button设置监听来调用三种解析方法对xml文件进行解析,并将解析出来的数据放在一个ListView中。
主界面: XMLParseActivity:
1 package cn.yj3g.XMLParseActivity; 2 3 import java.io.InputStream; 4 import java.util.ArrayList; 5 import java.util.HashMap; 6 import java.util.List; 7 import java.util.Map; 8 import android.app.ListActivity; 9 import android.content.res.AssetManager; 10 import android.os.Bundle; 11 import android.view.View; 12 import android.view.View.OnClickListener; 13 import android.widget.SimpleAdapter; 14 import cn.yj3g.TL23_xml_test.R; 15 import cn.yj3g.entity.Person; 16 import cn.yj3g.service.DomParseService; 17 import cn.yj3g.service.PullParseService; 18 import cn.yj3g.service.SAXParseService; 19 20 public class XMLParseActivity extends ListActivity implements 21 OnClickListener { 22 @Override 23 public void onCreate(Bundle savedInstanceState) { 24 super.onCreate(savedInstanceState); 25 setContentView(R.layout.main); 26 27 // 找到Button按钮并添加监听 28 findViewById(R.id.btn_dom).setOnClickListener(this); 29 findViewById(R.id.btn_sax).setOnClickListener(this); 30 findViewById(R.id.btn_pull).setOnClickListener(this); 31 } 32 33 public void onClick(View v) { 34 int id = v.getId(); 35 //定义一个List容器来存放Person对象 36 List<Person> list = null; 37 // 38 InputStream is = null; 39 AssetManager manager = getAssets(); 40 try { 41 //找到解析的文件 42 is = manager.open("persons.xml"); 43 switch (id) { 44 case R.id.btn_dom: 45 //调用DOM解析方法对文件进行解析 46 list = new DomParseService().getPersonsByParseXml(is); 47 break; 48 case R.id.btn_sax: 49 //调用SAX解析方法对文件进行解析 50 list = new SAXParseService().getPersonsByParseXml(is); 51 break; 52 case R.id.btn_pull: 53 //调用PULL解析方法对文件进行解析 54 list = new PullParseService().getPersonsByParseXml(is); 55 break; 56 default: 57 break; 58 } 59 } catch (Exception e) { 60 e.printStackTrace(); 61 } 62 showUI(list); 63 } 64 65 //运用Adapter方法将所得到的List<Person>显示在ListView中 66 public void showUI(List<Person> list) { 67 List<Map<String, Object>> data = new ArrayList<Map<String, Object>>(); 68 for (Person p : list) { 69 Map<String, Object> map = new HashMap<String, Object>(); 70 map.put("id", p.getId()); 71 map.put("name", p.getName()); 72 map.put("age", p.getAge()); 73 data.add(map); 74 } 75 String[] from = { "id", "name", "age" }; 76 int[] to = { R.id.tv_id, R.id.tv_name, R.id.tv_age }; 77 SimpleAdapter adapter = new SimpleAdapter(this, data, 78 R.layout.person_list_item, from, to); 79 setListAdapter(adapter); 80 } 81 }
我将布局文件也附在下面供大家参考吧。
main.xml:
<?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"> <LinearLayout android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="50dip" android:background="#222222"> <Button android:id="@+id/btn_dom" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="DOM显示" android:layout_weight="1.0" android:layout_gravity="center"/> <Button android:id="@+id/btn_sax" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="SAX显示" android:layout_weight="1.0" android:layout_gravity="center"/> <Button android:id="@+id/btn_pull" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="PULL显示" android:layout_weight="1.0" android:layout_gravity="center"/> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_height="wrap_content" android:layout_width="fill_parent"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="ID" android:layout_weight="1.0" android:layout_gravity="center"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="姓名" android:layout_weight="1.0" android:layout_gravity="center"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="年龄" android:layout_weight="1.0" android:layout_gravity="center"/> </LinearLayout> <ListView android:id="@android:id/list" android:layout_width="fill_parent" android:layout_height="fill_parent" android:layout_weight="1"/> </LinearLayout>
person_list_item.xml:
1 <?xml version="1.0" encoding="utf-8"?> 2 <LinearLayout 3 xmlns:android="http://schemas.android.com/apk/res/android" 4 android:orientation="horizontal" 5 android:layout_width="match_parent" 6 android:layout_height="match_parent"> 7 <TextView android:id="@+id/tv_id" 8 android:layout_width="match_parent" 9 android:layout_height="wrap_content" 10 android:layout_weight="1"/> 11 <TextView android:id="@+id/tv_name" 12 android:layout_width="match_parent" 13 android:layout_height="wrap_content" 14 android:layout_weight="1"/> 15 <TextView android:id="@+id/tv_age" 16 android:layout_width="match_parent" 17 android:layout_height="wrap_content" 18 android:layout_weight="1"/> 19 </LinearLayout>
这样我们这个项目就做好了,就可以实现解析xml的功能了。运行效果如最前面的效果图。
以上就是三种方式实现对XML文件的解析。希望大家不吝指教。