Android之XML文件解析
来源:互联网 发布:mmd虎视眈眈镜头数据 编辑:程序博客网 时间:2024/05/16 08:21
转载请注明出处:http://blog.csdn.net/joker_ya/article/details/38778971
OK!今天給带来的是Android对XML文件的解析方法。对于XML文件,有三种解析方法。它们分别是:SAX解析,DOM解析和PULL解析。下面我们就一个一个的来分析。
1.SAX解析
含义:SAX(simple API for XML)是一种XML解析的替代方法。相比于DOM,SAX是一种速度更快,更有效的方法。它逐行扫描文档,一边扫描一边解析。而且相比于DOM,SAX可以在解析文档的任意时刻停止解析,但任何事物都有其相反的一面,对于SAX来说就是操作复杂。
原理:SAX,它既是一个接口,也是一个软件包.但作为接口,SAX是事件驱动型XML解析的一个标准接口不会改变 SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
大多数SAX都会产生以下类型的事件:
1).在文档的开始和结束时触发文档处理事件。
2).在文档内每一XML元素接受解析的前后触发元素事件。
3).任何元数据通常由单独的事件处理
4).在处理文档的DTD或Schema时产生DTD或Schema事件。
5).产生错误事件用来通知主机应用程序解析错误。
2.DOM解析
DOM(Document Object Model)是一种用于XML 文档的对象模型,可用于直接访问XML文档的各个部分。文档都被组织成了数据结构上的树的形式,DOM解析以后可以将这个文档读到内存中并且以树的形式被组织。DOM比SAX更容易掌握,因为它没有涉及回调和复杂的状态管理。然而,DOM的实现常常将所有XML节点保持在内存中,这使处理较大的文档变得效率低下。尤其是对于小内存的手机而言。
通过DOM将XML文档作为一个树形结构,这种树形结构也被称为节点树,如下图所示。
3.PULL解析
PULL解析器的运行方式与SAX解析器相似。它提供了类似的事件,如开始元素和结束元素事件。使用parser.next()可以进入下一个元素并触发相应的事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行选择,然后进行相应的处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型元素的值。
和SAX不同的是,SAX的事件驱动是回调相应的方法,我们需要提供回调的方法,而后在SAX内部自动调用相应的方法。而PULL解析器并没有强制要求我们提供触发的方法。因为触发的事件并不是一个方法,而是一个数字。至于触发的事件要不要处理,就由程序员自己决定了。
好了,说了那么多了,都是一些含义、原理什么的。怪难理解的!那么,接下来就写一个Demo来帮助大家理解吧!
打开工程新建名为AnalysisXMLDemo的项目,目录结构如下:
首先给出我们要解析的XML文件persons.xml
<span style="font-size:18px;"><span style="font-size:18px;"><?xml version="1.0" encoding="utf-8"?><persons> <person id="1"> <name>张三</name> <age>20</age> </person> <person id="2"> <name>李四</name> <age>21</age> </person> <person id="3"> <name>王五</name> <age>22</age> </person> <person id="4"> <name>麻六</name> <age>23</age> </person> </persons></span></span>
然后我们新建一个Person.java类来接收解析的数据
<span style="font-size:18px;"><span style="font-size:18px;">package com.example.domain;/** * 创建一个Person类 * @author Joker_Ya * */public class Person {private int id;private String name;private short age;/** * 构造函数 */public Person() {}public Person(String name, short age) {this.name = name;this.age = age;}public Person(int id, String name, short age) {this.id = id;this.name = name;this.age = age;}/** * 变量的set和get方法 */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 short getAge() {return age;}public void setAge(short age) {this.age = age;}/** * toString方法 * @return */@Overridepublic String toString() {return "Person [id=" + id + ", name=" + name + ", age=" + age + "]";}}</span></span>
接下来就是编写SAX,DOM和PULL三种解析方法的解析代码了:
首先是SAX解析的代码SAXforHandler.java:
<span style="font-size:18px;"><span style="font-size:18px;">package com.example.analysisutils;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 android.util.Log;import com.example.domain.Person;/** * 新建SAXforHandler继承DefaultHandler, * 而DefaultHandler是实现了ContenHandler的接口,提供了相应的事件方法 * * @author Joker_Ya * */public class SAXforHandler extends DefaultHandler {private static final String TAG = "SAXforHandler";private List<Person> persons;private String perTag;// 记录前一个标签的名称private Person person;// 记录当前Personpublic List<Person> getPersons() {return persons;}/** * 对传入的InputStream流进行SAX解析并返回结果 * * @param inStream * InputStream流 * @return 返回解析到的Person的list列表 * @throws Exception * 抛出异常 */public static List<Person> sax_XML(InputStream inStream) throws Exception {SAXforHandler handler = new SAXforHandler();SAXParserFactory factory = SAXParserFactory.newInstance();SAXParser parser = factory.newSAXParser();parser.parse(inStream, handler);List<Person> list = handler.getPersons();inStream.close();return list;}/** * 通知应用程序文档的开始 适合在此事件中触发初始化行为, */@Overridepublic void startDocument() throws SAXException {// TODO Auto-generated method stubpersons = new ArrayList<Person>();// Log.v(TAG, "***startDocument()***");}/** * 通知应用程序元素的开始,属性作为Attributes参数传递 * * @param uri * 命名空间 * @param localName * 标签名称 * @param qName * 带命名空间的标签名 * @param attributes * 存放该标签的所有属性 */@Overridepublic void startElement(String uri, String localName, String qName,Attributes attributes) throws SAXException {// TODO Auto-generated method stubif ("person".equals(localName)) {for (int i = 0; i < attributes.getLength(); i++) {// Log.v(TAG,// "attributeName:"+attributes.getLocalName(i)+"_attributeValue:"+attributes.getValue(i));person = new Person();person.setId(Integer.valueOf(attributes.getValue(i)));}}perTag = localName;// Log.v(TAG, qName+"***startElement()***");}/** * 当语法分析器在元素中发现文本(已经解析过的字符数据)时,characters()会被应用程序触发 * * @param ch * 当前读取到的TextNode字节数组 * @param start * 字节开始的位置 * @param length * 当前TextNode的长度 */@Overridepublic void characters(char[] ch, int start, int length)throws SAXException {// TODO Auto-generated method stubString data = new String(ch, start, length).trim();if (!"".equals(data.trim())) {Log.v(TAG, "content:" + data.trim());}if ("name".equals(perTag)) {person.setName(data);} else if ("age".equals(perTag)) {person.setAge(new Short(data));}}/** * 通知应用程序元素的结束。 */@Overridepublic void endElement(String uri, String localName, String qName)throws SAXException {// TODO Auto-generated method stub// Log.v(TAG, qName+"***endElement()***");if ("person".equals(localName) && person != null) {persons.add(person);person = null;}perTag = null;}/** * 通知应用程序文档的结束 */@Overridepublic void endDocument() throws SAXException {// TODO Auto-generated method stub// Log.v(TAG, "***endDocument()***");}}</span></span>
然后是DOM解析的代码DomService.java:
<span style="font-size:18px;"><span style="font-size:18px;">package com.example.analysisutils;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import javax.xml.parsers.DocumentBuilder;import javax.xml.parsers.DocumentBuilderFactory;import org.w3c.dom.Document;import org.w3c.dom.Element;import org.w3c.dom.Node;import org.w3c.dom.NodeList;import com.example.domain.Person;/** * DOM解析核心代码 * @author Joker_Ya *整个解析过程我们可以参照上文中的节点树图,获得各个节点的顺序是严格按照树状结构的。 */public class DomService {public static List<Person> readXml(InputStream inStream) throws Exception {List<Person> persons = new ArrayList<Person>();//创建DocumentBuilderFactory,该对象将创建DocumentBuilderDocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();//创建DocumentBuilder,DocumentBuilder将实际进行解析以创建Document对象DocumentBuilder builder = factory.newDocumentBuilder();Document document = builder.parse(inStream);Element root = document.getDocumentElement();NodeList nodes = root.getElementsByTagName("person");for (int i = 0; i < nodes.getLength(); i++) {Element personElement = (Element) nodes.item(i);Person person = new Person();person.setId(Integer.parseInt((personElement.getAttribute("id"))));NodeList childNodes = personElement.getChildNodes();for (int y = 0; y < childNodes.getLength(); y++) {Node childNode = childNodes.item(y);if (childNode.getNodeType() == Node.ELEMENT_NODE) {Element childElement = (Element) childNode;if ("name".equals(childElement.getNodeName())) {person.setName(childElement.getFirstChild().getNodeValue());} else if ("age".equals(childElement.getNodeName())) {person.setAge(new Short(childElement.getFirstChild().getNodeValue()));}}}persons.add(person);}return persons;}}</span></span>
最后是PULL解析的代码PullService.java
<span style="font-size:18px;"><span style="font-size:18px;">package com.example.analysisutils;import java.io.InputStream;import java.util.ArrayList;import java.util.List;import org.xmlpull.v1.XmlPullParser;import android.util.Xml;import com.example.domain.Person;/** * PULL解析核心代码 * @author Joker_Ya * */public class PullService {public static List<Person> readXml(InputStream inStream) throws Exception {List<Person> persons = null;XmlPullParser parser = Xml.newPullParser();parser.setInput(inStream, "UTF-8");//得到PULL解析器的事件,其返回值是int类型的int eventCode = parser.getEventType();Person person = null;// 用switch循环,如果获得的事件码是文档结束,那么结束解析(parser.next()来触发下一事件)while (eventCode != XmlPullParser.END_DOCUMENT) {switch (eventCode) {case XmlPullParser.START_DOCUMENT:// 文档开始事件persons = new ArrayList<Person>();break;case XmlPullParser.START_TAG:// 开始元素// 判断当前元素是否是需要检索的元素if ("person".equals(parser.getName())) {person = new Person();person.setId(Integer.parseInt(parser.getAttributeValue(0)));} else if (person != null) {if ("name".equals(parser.getName())) {person.setName(parser.nextText());} else if ("age".equals(parser.getName())) {person.setAge(new Short(parser.nextText()));}}break;case XmlPullParser.END_TAG:// 结束元素if ("person".equals(parser.getName()) && person != null) {persons.add(person);person = null;}break;default:break;}//下一个事件,是parser中最重要的方法eventCode = parser.next();}return persons;}}</span></span>
至此关于SAX解析,DOM解析和PULL解析的核心代码全部给出来了。其实弄懂了它们的原理和解析时的顺序就很容易了。
下面就是界面activity_main.xml:
<span style="font-size:18px;"><span style="font-size:18px;"><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity" ><LinearLayout android:layout_width="fill_parent" android:layout_height="fill_parent" android:orientation="vertical" > <Button android:id="@+id/sax_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="SAX解析XML" /> <Button android:id="@+id/dom_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="DOM解析XML" /> <Button android:id="@+id/pull_button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="PULL解析XML" /> <TextView android:id="@+id/showtext" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <ListView android:id="@+id/listview" android:layout_width="fill_parent" android:layout_height="wrap_content" ></ListView> </LinearLayout></RelativeLayout></span></span>
接下来就是MainActivity.java:
<span style="font-size:18px;"><span style="font-size:18px;">package com.example.analysisxmldemo;import java.io.InputStream;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.util.Map;import com.example.analysisutils.DomService;import com.example.analysisutils.PullService;import com.example.analysisutils.SAXforHandler;import com.example.domain.Person;import android.os.Bundle;import android.app.Activity;import android.view.View;import android.view.View.OnClickListener;import android.widget.ArrayAdapter;import android.widget.Button;import android.widget.ListView;import android.widget.SimpleAdapter;import android.widget.TextView;/** * * @author Joker_Ya * */public class MainActivity extends Activity implements OnClickListener {private Button sax_button;private Button dom_button;private Button pull_button;private TextView showtext;private ListView listView;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);sax_button = (Button) findViewById(R.id.sax_button);dom_button = (Button) findViewById(R.id.dom_button);pull_button = (Button) findViewById(R.id.pull_button);showtext = (TextView) findViewById(R.id.showtext);listView = (ListView) findViewById(R.id.listview);sax_button.setOnClickListener(this);dom_button.setOnClickListener(this);pull_button.setOnClickListener(this);}/** * 按钮的点击事件判断和处理。 */@Overridepublic void onClick(View v) {// TODO Auto-generated method stubswitch (v.getId()) {case R.id.sax_button://点击了“SAX解析XML”按钮try {// 用类装载器得到persons.xml文件的输入流InputStream is = MainActivity.class.getClassLoader().getResourceAsStream("persons.xml");List<Person> persons;persons = SAXforHandler.sax_XML(is);List<Map<String, String>> lists = new ArrayList<Map<String, String>>();Map<String, String> hasmap;String[] Strpersons = new String[persons.size()];for (int i = 0; i < persons.size(); i++) {hasmap = new HashMap<String, String>();hasmap.put("number", Strpersons[i] = persons.get(i).toString() + "by SAX");lists.add(hasmap);}showtext.setText("使用SAX解析persons.xml");//新建一个SimpleAdapter适配器SimpleAdapter adapter = new SimpleAdapter(this, lists,android.R.layout.simple_list_item_1,new String[] { "number" },new int[] { android.R.id.text1 });//将解析的数据在listView中显示listView.setAdapter(adapter);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}break;case R.id.dom_button://点击了“DOM解析XML”按钮try {InputStream is = MainActivity.class.getClassLoader().getResourceAsStream("persons.xml");List<Person> persons;persons = DomService.readXml(is);String[] Strpersons = new String[persons.size()];for (int i = 0; i < persons.size(); i++) {Strpersons[i] = persons.get(i).toString() + "by DOM";}showtext.setText("使用DOM解析persons.xml");//新建一个ArrayAdapter适配器ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, Strpersons);listView.setAdapter(adapter);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}break;case R.id.pull_button://点击了“PULL解析XML”按钮try {InputStream is = MainActivity.class.getClassLoader().getResourceAsStream("persons.xml");List<Person> persons;persons = PullService.readXml(is);String[] Strpersons = new String[persons.size()];for (int i = 0; i < persons.size(); i++) {Strpersons[i] = persons.get(i).toString() + "by PULL";}showtext.setText("使用PULL解析persons.xml");ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,android.R.layout.simple_list_item_1, Strpersons);listView.setAdapter(adapter);} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();}break;default:break;}}}</span></span>
在这里要说明一点,就是使用SAX解析得到返回的数据并用ListView显示时。如果用ArrayAdapter适配器来绑定数据时,程序会报错。因此SAX解析那里使用了SimpleAdapter适配器来绑定数据。至于为什么会报错,个人觉得是适配器的问题,如果有哪位大神知道的麻烦告诉我一下。感谢。
最后的最后就是给出结果图了:
首先是程序初始运行图:
点击SAX解析XML按钮图:
点击DOM解析XML按钮图:
点击PULL解析XML按钮图:
噢,还有最后,那就是源代码下载地址
AnalysisXMLDemo
- Android之XML文件解析
- Android之解析XML文件
- android之解析xml文件
- android之sax解析xml文件
- Android开发之XML文件解析
- Android之SAX解析XML文件
- Android之DOM解析XML文件
- android之sax解析xml文件
- android之sax解析xml文件 .
- Android之AndroidManifest.xml文件解析
- Android学习之AndroidManifest.xml文件解析
- android之sax解析xml文件
- Android之 AndroidManifest.xml 文件解析
- android之sax解析xml文件
- Android开发之XML文件解析
- Android开发之XML文件的解析
- android解析xml文件之XmlPullParser
- Android之AndroidManifest.xml文件解析
- poj1015——Jury Compromise
- java时间公用辅助类
- 《javascript设计模式》读书笔记一(接口)
- Trie字典树【模板
- R语言
- Android之XML文件解析
- mongodb 使用场景和不使用场景
- Lession 30 输入输出流
- hdu4979 A simple math problem.Dancing Links,打表
- AC自动机 病毒侵袭 hdu2896
- 正则表达式
- linux文件操作总结
- 家纺网数据表分析
- 图像信息熵matlab代码