Android中解析xml的几种方式
16lz
2021-01-24
1.android 使用pull生成xml
有些时候,我们需要生成一个XML文件,生成XML文件的方法有很多,如:可以只使用一个StringBuilder组拼XML内容,然后把内容写入到文件中;或者使用DOM API生成XML文件,或者也可以使用pull解析器生成XML文件,在android等移动设备上推荐大家使用Pull解析器
生成实现代码:
[java] view plain copy- packagecom.scl.parse;
- importjava.io.OutputStream;
- importjava.io.Writer;
- importjava.util.List;
- importorg.xmlpull.v1.XmlSerializer;
- importandroid.util.Xml;
- importcom.scl.domain.Person;
- publicclassPullCreatXml{
- /**
- *使用输出流的方式
- *@parampersons
- *@paramout
- *@throwsException
- */
- publicvoidcreatPersonXml(List<Person>persons,OutputStreamout)throwsException{
- XmlSerializerserializer=Xml.newSerializer();
- serializer.setOutput(out,"utf-8");
- //文档开始
- serializer.startDocument("utf-8",true);
- //开始persons标签
- serializer.startTag(null,"persons");
- for(Personperson:persons){
- //开始person标签
- serializer.startTag(null,"person");
- serializer.attribute(null,"id",person.getId().toString());
- serializer.startTag(null,"name");
- serializer.text(person.getName());
- serializer.endTag(null,"name");
- serializer.startTag(null,"age");
- serializer.text(person.getAge().toString());
- serializer.endTag(null,"age");
- //结束person标签
- serializer.endTag(null,"person");
- }
- //结束persons标签
- serializer.endTag(null,"persons");
- //文档结束
- serializer.endDocument();
- out.flush();
- out.close();
- }
- /**
- *使用Writer方式
- *@parampersons
- *@paramwriter
- *@throwsException
- */
- publicvoidcreatPersonXml2(List<Person>persons,Writerwriter)throwsException{
- XmlSerializerserializer=Xml.newSerializer();
- serializer.setOutput(writer);
- //文档开始
- serializer.startDocument("utf-8",true);
- //开始persons标签
- serializer.startTag(null,"persons");
- for(Personperson:persons){
- //开始person标签
- serializer.startTag(null,"person");
- serializer.attribute(null,"id",person.getId().toString());
- serializer.startTag(null,"name");
- serializer.text(person.getName());
- serializer.endTag(null,"name");
- serializer.startTag(null,"age");
- serializer.text(person.getAge().toString());
- serializer.endTag(null,"age");
- //结束person标签
- serializer.endTag(null,"person");
- }
- //结束persons标签
- serializer.endTag(null,"persons");
- //文档结束
- serializer.endDocument();
- writer.flush();
- writer.close();
- }
- }
单元测试代码
[java] view plain copy
- publicvoidtestPullCreatXmlTest()throwsThrowable{
- FileOutputStreamout=this.getContext().openFileOutput("person.xml",Context.MODE_PRIVATE);
- PullCreatXmlcreatXml=newPullCreatXml();
- List<Person>persons=newArrayList<Person>();
- persons.add(newPerson(1,"杨过",newShort("15")));
- persons.add(newPerson(2,"段誉",newShort("25")));
- creatXml.creatPersonXml(persons,out);
- }
- publicvoidtestPullCreatXmlTest2()throwsThrowable{
- FileOutputStreamout=this.getContext().openFileOutput("person2.xml",Context.MODE_PRIVATE);
- PullCreatXmlcreatXml=newPullCreatXml();
- List<Person>persons=newArrayList<Person>();
- persons.add(newPerson(1,"杨过",newShort("15")));
- persons.add(newPerson(2,"段誉",newShort("25")));
- OutputStreamWriterwriter=newOutputStreamWriter(out,"utf-8");
- creatXml.creatPersonXml2(persons,writer);
- }
- /**返回字符串*/
- publicvoidtestPullCreatXmlTest3()throwsThrowable{
- PullCreatXmlcreatXml=newPullCreatXml();
- List<Person>persons=newArrayList<Person>();
- persons.add(newPerson(1,"杨过",newShort("15")));
- persons.add(newPerson(2,"段誉",newShort("25")));
- StringWriterwriter=newStringWriter();
- creatXml.creatPersonXml2(persons,writer);
- Log.i(TAG,writer.toString());
- }
2.android使用pull方式解析xml
Pull解析器的运行方式与SAX解析器相似。它提供了类似的事件,如:开始元素和结束元素事件,使用parser.next()可以进入下一个元素并触发相应事件。事件将作为数值代码被发送,因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法可以获取下一个Text类型节点的值。
[java] view plain copy
- packagecom.scl.parse;
- importjava.io.InputStream;
- importjava.util.ArrayList;
- importjava.util.List;
- importorg.xmlpull.v1.XmlPullParser;
- importcom.scl.domain.Person;
- importandroid.util.Xml;
- publicclassPullParsePerson{
- publicList<Person>getPerson(InputStreamin)throwsException{
- List<Person>persons=null;
- Personperson=null;
- //获得pull解析器
- XmlPullParserparser=Xml.newPullParser();
- //往解析器里放入输入流
- parser.setInput(in,"UTF-8");
- //获得事件类型
- inteventType=parser.getEventType();
- while(eventType!=XmlPullParser.END_DOCUMENT){
- switch(eventType){
- //在文档开头初始化一些数据
- caseXmlPullParser.START_DOCUMENT:
- persons=newArrayList<Person>();
- break;
- //开始某个节点
- caseXmlPullParser.START_TAG:
- if("person".equals(parser.getName())){
- person=newPerson();
- person.setId(newInteger(parser.getAttributeValue(0)));
- }
- if(person!=null){
- if("name".equals(parser.getName())){
- person.setName(parser.nextText());
- }
- if("age".equals(parser.getName())){
- person.setAge(newShort(parser.nextText()));
- }
- }
- break;
- //结束某个节点
- caseXmlPullParser.END_TAG:
- if("person".equals(parser.getName())){
- persons.add(person);
- person=null;
- }
- break;
- }
- //获得下一个事件类型
- eventType=parser.next();
- }
- //文档解析结束
- returnpersons;
- }
- }
3.Android中使用Dom解析xml
除了使用 SAX可以解析XML文件,大家也可以使用熟悉的DOM来解析XML文件。 DOM解析XML文件时,会将XML文件的所有内容以文档树方式存放在内存中,然后允许您使用DOMAPI遍历XML树、检索所需的数据。使用DOM操作XML的代码看起来是比较直观的,并且在编码方面比基于SAX的实现更加简单。但是,因为DOM需要将XML文件的所有内容以文档树方式存放在内存中,所以内存的消耗比较大,特别对于运行Android的移动设备来说,因为设备的资源比较宝贵,所以建议还是采用SAX来解析XML文件,当然,如果XML文件的内容比较小采用DOM也是可行的。下面是实现代码[java] view plaincopypackage com.scl.parse; 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.scl.domain.Person; public class DOMParsePerson { public List<Person> getPersons(InputStream in) throws Throwable{ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); //装载成document树对象 Document document = builder.parse(in); //获得根节点 Element root = document.getDocumentElement(); //获得根节点的子节点 NodeList persons = root.getElementsByTagName("person"); //遍历所有person节点 List<Person> personsList = new ArrayList<Person>(); for(int i = 0;i < persons.getLength(); i ++){ Person person = new Person(); //获得一个person节点 Element personElement = (Element)persons.item(i); //获得一个person节点的id属性,并把id的值设置给person person.setId(new Integer(personElement.getAttribute("id"))); NodeList childNodes = personElement.getChildNodes(); //循环person节点的子节点 for(int j = 0;j < childNodes.getLength();j++){ Node child = childNodes.item(j); if(child.getNodeType() == Node.ELEMENT_NODE){ Element e = (Element)child; if("name".equals(child.getNodeName())){ person.setName(child.getFirstChild().getNodeValue()); } else if("age".equals(child.getNodeName())){ person.setAge(new Short(child.getFirstChild().getNodeValue())); } } } personsList.add(person); } return personsList; } } 下面是单元测试代码[java] view plaincopypublic void testDOMParserTest() throws Throwable{ InputStream in = this.getClass().getClassLoader().getResourceAsStream("person.xml"); DOMParsePerson dom = new DOMParsePerson(); List<Person> persons = dom.getPersons(in); for(Person p : persons){ Log.i(TAG, p.toString()); } }
4.Android中使用SAX解析xml
SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于Android等移动设备。 SAX解析XML文件采用的是事件驱动,也就是说,它并不需要解析完整个文档,在按内容顺序解析文档的过程中,SAX会判断当前读到的字符是否合法XML语法中的某部分,如果符合就会触发事件。所谓事件,其实就是一些回调(callback)方法,这些方法(事件)定义在ContentHandler接口。下面是一些ContentHandler接口常用的方法:startDocument()当遇到文档的开头的时候,调用这个方法,可以在其中做一些预处理的工作。endDocument()和上面的方法相对应,当文档结束的时候,调用这个方法,可以在其中做一些善后的工作。startElement(String namespaceURI, String localName, String qName, Attributes atts)当读到一个开始标签的时候,会触发这个方法。namespaceURI就是命名空间,localName是不带命名空间前缀的标签名,qName是带命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。要注意的是SAX中一个重要的特点就是它的流式处理,当遇到一个标签的时候,它并不会纪录下以前所碰到的标签,也就是说,在startElement()方法中,所有你所知道的信息,就是标签的名字和属性,至于标签的嵌套结构,上层标签的名字,是否有子元属等等其它与结构相关的信息,都是不得而知的,都需要你的程序来完成。这使得SAX在编程处理上没有DOM来得那么方便。endElement(String uri, String localName, String name)这个方法和上面的方法相对应,在遇到结束标签的时候,调用这个方法。characters(char[] ch, int start, int length)这个方法用来处理在XML文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,使用new String(ch,start,length)就可以获取内容。 person.xml[html] view plaincopy<?xml version="1.0" encoding="UTF-8"?> <persons> <person id="22"> <name>张三丰</name> <age>60</age> </person> <person id="2"> <name>小龙女</name> <age>21</age> </person> </persons> Person.java 类[java] view plaincopypackage com.scl.domain; public class Person { private Integer id; private String name; private Short age; public Integer getId() { return id; } public void setId(Integer 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; } @Override public String toString() { return "id:" + id + ",name:" + name + ",age:" + age; } } 只要为SAX提供实现ContentHandler接口的类,那么该类就可以得到通知事件(实际上就是SAX调用了该类中的回调方法)。因为ContentHandler是一个接口,在使用的时候可能会有些不方便,因此,SAX还为其制定了一个Helper类:DefaultHandler,它实现了ContentHandler接口,但是其所有的方法体都为空,在实现的时候,你只需要继承这个类,然后重写相应的方法即可。使用SAX解析person.xml的代码如下:[java] view plaincopypackage com.scl.parse; 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 com.scl.domain.Person; public class SAXParsePerson { public List<Person> getPersons(InputStream in) throws Throwable { SAXParserFactory factory = SAXParserFactory.newInstance(); SAXParser parser = factory.newSAXParser(); PersonParser personParser = new PersonParser(); parser.parse(in,personParser); in.close(); return personParser.getPersons(); } private final class PersonParser extends DefaultHandler{ private List<Person> persons = null; private Person person = null; private String tag = null; public List<Person> getPersons(){ return persons; } @Override public void startDocument() throws SAXException { persons = new ArrayList<Person>(); } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { if("person".equals(localName)){ person = new Person(); //attributes.getValue(0);这是获取第几个属性的值的方法 //下面这个是通过属性名称获得属性值 person.setId(new Integer(attributes.getValue("id"))); } tag = localName; } @Override public void endElement(String uri, String localName, String qName) throws SAXException { if("person".equals(localName)){ persons.add(person); person = null; } tag = null; } @Override public void characters(char[] ch, int start, int length) throws SAXException { if(tag!=null){ String value = new String(ch, start, length); if("name".equals(tag)){ person.setName(value); } else if("age".equals(tag)){ person.setAge(new Short(value)); } } } } } 单元测试代码[java] view plaincopypackage com.scl.xml.test; import java.io.InputStream; import java.util.List; import com.scl.domain.Person; import com.scl.parse.SAXParsePerson; import android.test.AndroidTestCase; import android.util.Log; public class XMPParseTest extends AndroidTestCase { private static final String TAG = "XMPParseTest"; public void testSAXParserTest() throws Throwable{ InputStream in = this.getClass().getClassLoader().getResourceAsStream("person.xml"); SAXParsePerson sax = new SAXParsePerson(); List<Person> persons = sax.getPersons(in); for(Person p : persons){ Log.i(TAG, p.toString()); } } }
更多相关文章
- Android学习杂记(二):异步任务AsyncTask详解
- Android基本数据存储方法
- Android安装常见的一些解决方法
- android几种定时器机制及区别
- Android本地服务的启动 - zygote服务及Dalvik环境启动
- Android(安卓)实现ListView的弹性效果
- Android,如何在代码中获取attr属性的值
- 快速掌握 Android(安卓)Studio 中 Gradle 的使用方法
- Android:自定义DialogFragment的内容和按钮