Android学习笔记_7_使用 sax 或者 dom 或者 pull 解析XML文件
一、Pull解析介绍:
Android上使用SAX和DOM方式解析XML的方法,并且对两种做了简单的比较,通过比较我们知道对在往往内存比较稀缺的移动设备上运行的Android系统来说,SAX是一种比较合适的XML解析方式。但是SAX方式的特点是需要解析完整个文档才会返回,如果在一个XML文档中我们只需要前面一部分数据,但是使用SAX方式还是会对整个文档进行解析,尽管XML文档中后面的大部分数据我们其实都不需要解析,因此这样实际上就浪费了处理资源。
Pull解析器和SAX解析器虽有区别但也有相似性。他们的区别为:SAX解析器的工作方式是自动将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束;而Pull解析器的工作方式为允许你的应用程序代码主动从解析器中获取事件,正因为是主动获取事件,因此可以在满足了需要的条件后不再获取事件,结束解析。这是他们主要的区别。而他们的相似性在运行方式上,Pull解析器也提供了类似SAX的事件(开始文档START_DOCUMENT和结束文档END_DOCUMENT,开始元素START_TAG和结束元素END_TAG,遇到元素内容TEXT等),但需要调用next() 方法提取它们(主动提取事件)。
Android系统中和Pull方式相关的包为org.xmlpull.v1,在这个包中提供了Pull解析器的工厂类XmlPullParserFactory和Pull解析器XmlPullParser,XmlPullParserFactory实例调用newPullParser方法创建XmlPullParser解析器实例,接着XmlPullParser实例就可以调用getEventType()和next()等方法依次主动提取事件,并根据提取的事件类型进行相应的逻辑处理。
二、准备xml文件:
文件保存在src目录下
<?xml version="1.0" encoding="UTF-8"?> <persons> <person id="1001"> <name>张三</name> <age>27</age> </person> <person id="1002"> <name>李四</name> <age>25</age> </person> <person id="1003"> <name>王五</name> <age>28</age> </person> <person id="1004"> <name>赵六</name> <age>30</age> </person> </persons>
三、通过Pull解析和保存实现:
package com.example.service; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlSerializer; import android.util.Xml; import com.example.entity.Person; public class XMLParse { /** * 解析xml * @param in 输入流 * @return */ public List<Person> parse(InputStream in) { List<Person> persons=null; Person person=null; try { //创建XmlPullParser,有两种方式 //方式一:使用工厂类XmlPullParserFactory // XmlPullParserFactory pullFactory = XmlPullParserFactory.newInstance(); // XmlPullParser xmlPullParser = pullFactory.newPullParser(); // //方式二:使用Android提供的实用工具类android.util.Xml XmlPullParser xmlPullParser = Xml.newPullParser(); xmlPullParser.setInput(in, "UTF-8"); int event = xmlPullParser.getEventType(); boolean isDone = false; //具体解析xml while ((event != XmlPullParser.END_DOCUMENT)&&(isDone != true)) { switch (event) { case XmlPullParser.START_DOCUMENT: persons = new ArrayList<Person>(); break; case XmlPullParser.START_TAG: if("person".equals(xmlPullParser.getName())){ person = new Person(); int id = Integer.valueOf(xmlPullParser.getAttributeValue(0)); person.setId(id); } if("name".equals(xmlPullParser.getName())){ person.setName(xmlPullParser.nextText()); } if("age".equals(xmlPullParser.getName())){ person.setAge(Integer.valueOf(xmlPullParser.nextText())); } break; case XmlPullParser.END_TAG: if("person".equals(xmlPullParser.getName())){ persons.add(person); person=null; } break; } //调用next()方法主动提取事件 event = xmlPullParser.next(); } } catch (Exception e) { e.printStackTrace(); } return persons; } /** * 将对象保存成xml文件 * @param out * @param persons */ public void save(OutputStream out,List<Person> persons){ try { XmlSerializer xml = Xml.newSerializer(); xml.setOutput(out, "UTF-8"); xml.startDocument("UTF-8", true); xml.startTag(null, "persons"); for (Person person : persons) { xml.startTag(null, "person"); //设置属性 xml.attribute(null, "id", person.getId().toString()); xml.startTag(null, "name"); xml.text(person.getName());//设置内容 xml.endTag(null, "name"); xml.startTag(null, "age"); xml.text(person.getAge().toString()); xml.endTag(null, "age"); xml.endTag(null, "person"); } xml.endTag(null, "persons"); xml.endDocument(); out.flush();//防止是缓冲流 out.close(); } catch (Exception e) { e.printStackTrace(); } } }
四、测试与结果:
package com.example.test; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.InputStream; import java.util.ArrayList; import java.util.List; import android.test.AndroidTestCase; import android.util.Log; import com.example.entity.Person; import com.example.service.XMLParse; public class XMLParseTest extends AndroidTestCase { private static String TAG ="XMLParseTest"; public void testParse() { XMLParse p = new XMLParse(); //Person.xml文件在src目录下 InputStream in = XMLParseTest.class.getClassLoader().getResourceAsStream("Person.xml"); List<Person> persons = p.parse(in); for (Person person : persons) { Log.i(TAG, person.toString()); } } public void testSave() { try { XMLParse p = new XMLParse(); List<Person> persons=new ArrayList<Person>(); persons.add(new Person(10001,"tom",25)); persons.add(new Person(10002,"lily",26)); persons.add(new Person(10003,"xiaoming",27)); //将文件保存在当前应用所在包的files文件夹下 FileOutputStream fos=new FileOutputStream(new File(getContext().getFilesDir(),"xiaoming.xml")); p.save(fos, persons); } catch (Exception e) { e.printStackTrace(); } } }
将对象生成xml文件及保存位置:
<?xml version='1.0' encoding='UTF-8' standalone='yes' ?> <persons> <person id="10001"> <name>tom</name> <age>25</age> </person> <person id="10002"> <name>lily</name> <age>26</age> </person> <person id="10003"> <name>xiaoming</name> <age>27</age> </person> </persons>
结果(在LogCat中加入XMLParseTest标签):
二、SAX解析介绍:
在SAX接口中,事件源是org.xml.sax包中的XMLReader,它通过parser()方法来解析XML文档,并根据文档的内容产生事件。而事件处理器则是org.xml.sax包中的ContentHander、DTDHander、ErrorHandler,以及EntityResolver这4个接口,它们分别处理事件源在解析XML文档过程中产生的不同种类的事件。在开发中没有必要直接从这4个接口直接继承,因为org.xml.sax.helper包提供了类DefaultHandler,其继承了这4个接口,在实际开发中直接从DefaultHandler继承并实现相关函数就可以了。
1、实体类和需要解析的xml配置文件:
public class Person { private String id; private String name; private String age; private String address; }
<?xml version="1.0" encoding="UTF-8"?> <persons> <person> <id>1001</id> <name>小王</name> <age>信息学院</age> <address>6258113</address> </person> <person> <id>1002</id> <name>小李</name> <age>信息学院</age> <address>12312</address> </person> </persons>
2、解析
package cn.sax.test; import java.io.InputStream; import java.util.ArrayList; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import org.xml.sax.XMLReader; import org.xml.sax.helpers.DefaultHandler; public class SAXXmlService extends DefaultHandler { // //定义一个Person引用 Person person = null; // 此处将XML里的数据封装成Person类,personList用于装解析后的数据 ArrayList<Person> personArr = null; // 定义一个标记变量,标记当前的XML文件被解析到哪个标签 private String currentTag = null; /* * 执行解析 */ public static ArrayList<Person> getPersonInfos(InputStream stream) throws Exception { // 得到SAX解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); // 创建解析器 SAXParser parser = factory.newSAXParser(); XMLReader xmlreader = parser.getXMLReader(); // 得到输入流 InputSource is = new InputSource(stream); // 得到SAX解析实现类 SAXXmlService handler = new SAXXmlService(); xmlreader.setContentHandler(handler); // 开始解析 xmlreader.parse(is); return handler.personArr; } @Override public void characters(char[] ch, int start, int length) throws SAXException { super.characters(ch, start, length); // 判断当前标签是否有效 if (currentTag != null) { // //读取标签里面的内容 String value = new String(ch, start, length); System.out.println("value"+value); // 如果是Id标签,则读取Id标签的内容设置到Person的ID值上 if ("id".equalsIgnoreCase(currentTag)) { person.setId(value); } else if ("name".equalsIgnoreCase(currentTag)) {// name标签 person.setName(value); } else if ("age".equalsIgnoreCase(currentTag)) { // age标签 person.setAge(value); } else if ("address".equalsIgnoreCase(currentTag)) { // address标签 person.setAddress(value); } } } /* 解析XML时,当开始读取XML文档时 */ @Override public void startDocument() throws SAXException { personArr = new ArrayList<Person>(); } @Override public void endDocument() throws SAXException { super.endDocument(); } /* 解析XML时,当开始读到一个元素标签开始时 */ @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if (qName.equals("person")) { person = new Person(); } currentTag = qName; } /* 解析XML时,当读到结束一个元素标签时 */ @Override public void endElement(String uri, String localName, String qName) throws SAXException { // 将当前标签名置空 currentTag = null; // 如果当前结束的标签名是person的话,代表一个person对象已经读取完毕。将其添加到list后置空 if (qName.equals("person")) { personArr.add(person); person = null; } } }
3、测试
public class Test { public static void main(String[] args) { InputStream stream; try { File file = new File("src/NewFile.xml"); stream = new FileInputStream(file); List<Person> persons = SAXXmlService.getPersonInfos(stream); for (Person person : persons) { System.out.println(person); } } catch (Exception e) { e.printStackTrace(); } } }