Anroid开发之Xml的解析
来源:互联网 发布:虾米音乐mac版客户端 编辑:程序博客网 时间:2024/06/09 17:10
在前面的一个博客中我们了解了json数据的解析,现在我们来实现对xml格式的数据的解析,xml是一种可扩展标记语言,是由标签组成的。方便我们读取数据。 xml的解析有三种方式,DOM解析,SAX解析,PULL解析。
- DOM解析XML文件时,会将XML文件所有内容都读取到内存中,然后再遍历XML文件树,检索需要的数据。DOM解析XML有很大的缺陷,对内存的消耗比较大,影响系统的性能,所以我这里没有详细讲DOM解析。
- SAX解析是一种占用内存少,且解析速度快的解析器,它采用事件驱动,它不需要解析整个文档,而是按照顺序,检索XML文件是否符合XML的语法,当符合时会触发相应的回调函数。这些函数是在ContentHander中,我们可以重写这些方法来实现我们对数据的解析。
- Pull解析是一种可以解析部分XML文件的解析方式,当我们只需要XML文件中的一部分数据时,用这种方法是非常好的。Pull解析和SAX解析类似,SAX解析器工作方式是自动的将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束,而Pull解析的工作方式为允许你的应用程序代码主动从解析器获取事件,因此我们可以在获取了我们需要的数据时,主动结束解析。
SAX解析
SAX解析的主要是重写ContentHander中回调方法,在其中主要的是:
- startDocument:当遇到文档时候触发事件。
- startElement:当遇到开始标签时触发。
- endElement:当遇到结束标签时触发。
- characters:当遇到xml内容时触发。
上面是我自己建的一个xml文件,命名为students.xml,并将它放在assets文件夹下。
1.我首先定义了一个student类对象,用来存放解析出来的xml数据
public class Student { private Long Id; private String Name; private String Speciality; private Long QQ; public Student() { } //省略了get和set方法}
2.实例化一个SAX工厂,并获取SAX解析器,读取xml文件,创建回调函数
protected List<Student> parserXML() { //实例化一个SAX解析工厂 SAXParserFactory factory = SAXParserFactory.newInstance(); List<Student> studnets = null; //获取XML解析器 try { XMLReader reader = factory.newSAXParser().getXMLReader(); studnets = new ArrayList<Student>(); //设置回调函数,这里是我自定义的回调函数 reader.setContentHandler(new StudentHander(studnets)); //读取Assets下的student.xml文件 reader.parse(new InputSource(SAXXMLActivity.this. getResources().getAssets().open("students.xml"))); } catch (SAXException e) { e.printStackTrace(); } catch (ParserConfigurationException e) { e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } return studnets;
3.自定义StudentHander回调函数,继承自DefaultHander;在回调方法里解析出自己需要的数据。其中preTAG用来存储当前节点名称,在endElement中要记得滞空。
public class StudentHander extends DefaultHandler { private String preTAG; private List<Student> ListStudent; private Student stu; public StudentHander() { } public StudentHander(List<Student> listStudent) { super(); ListStudent = listStudent; } //开始解析文档 @Override public void startDocument() throws SAXException { Log.i("----->", "开始解析文档!"); super.startDocument(); } //开始解析文档元素 @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { Log.i("localName----->", localName); preTAG = localName; if ("student".equals(localName)) { stu = new Student(); //将ID保存在stu中 stu.setId(Long.parseLong(attributes.getValue(0))); for (int i = 0; i < attributes.getLength(); i++) { Log.i("attribute----->", String.valueOf(stu.getId())); } } //这句话记得要执行 super.startElement(uri, localName, qName, attributes); } @Override public void endDocument() throws SAXException { Log.i("----->", "文档结束"); super.endDocument(); } @Override public void endElement(String uri, String localName, String qName) throws SAXException { preTAG = ""; if ("student".equals(localName)) { ListStudent.add(stu); Log.i("----->", "一个元素解析完成!"); } super.endElement(uri, localName, qName); } //解析节点文本内容 @Override public void characters(char[] ch, int start, int length) throws SAXException { String str; //找出元素中的name节点 if ("name".equals(preTAG)) { str = new String(ch,start,length); stu.setName(str); Log.i("name=", str); }else if("speciality".equals(preTAG)){ str = new String(ch,start,length); stu.setSpeciality(str); Log.i("speciality=", str); }else if("qq".equals(preTAG)){ str = new String(ch,start,length); stu.setQQ(Long.parseLong(str)); Log.i("qq=", str); } super.characters(ch, start, length); } public void setListStudent(List<Student> listStudent) { ListStudent = listStudent; } public List<Student> getListStudent() { return ListStudent; }}
这样我们就解析出xml的整个数据了,并在回调函数中将数据保存到了数组对象students中,我们查看一下打印出的log,分析一下SAX的解析过程。
我们可以看出这种按顺序解析XML文件标签的方式,完全符合回调函数中的说明。清晰明了。
Pull解析
pull解析和我们上面的SAX解析方法有些类似,Pull解析也提供了类似SAX的事件:
- START_DOCUMENT:开始文档;
- START_TAG:开始元素;
- TEXT:遇到元素内容;
- END_TAG:结束元素
- END_DOCUMENT:结束文档
Android系统提供了Pull解析的包org.xmlpull.v1,里面有PUll解析工厂类XMLPullParserFactory,和PULL解析器XmlParser。我们实例化工厂类,并获取xml解析器,接着XmlParser实例就可以调用getEventType()和next()等方法主动提取事件,并根据提取的事件做数据的处理。
PULL解析器有两种获取方法:
- 通过工厂类XMLPullParserFactory
- 通过Android实用工具类
protected List<Student> parserXML() { //初始化一个List<student>变量,用于存放student成员 List<Student> studnets = null; //初始化student对象,用于存储每一个节点的信息 Student stu = null; try { //打开资源文件 InputStream inputStream = PullXMLActivity.this.getResources() .getAssets().open("students.xml"); //创建XmlParser有两种方法 //方法一:使用工厂类XmlPullParserFactory XmlPullParserFactory pullFactory = XmlPullParserFactory.newInstance(); XmlPullParser xmlPullParser = pullFactory.newPullParser(); /* * //方法二:使用Android提供的实用工具类android.util.Xml //XmlPullParser xmlPullParser = Xml.newPullParser(); //设置输入字节流为UTF-8编码 * */ xmlPullParser.setInput(inputStream, "utf-8"); //取得事件类型,用于开始时的判断 int eventType = xmlPullParser.getEventType(); //循环遍历整个文件直到结束 while(eventType != XmlPullParser.END_DOCUMENT){ /* * 输出log显示事件类型 * START_DOCUMENT:0 * */ Log.i("--->event", eventType+" "); //用于存储节点名称 String localName = ""; switch (eventType) { case XmlPullParser.START_DOCUMENT: //碰到文档开头则实例化students变量,并输出log studnets = new ArrayList<Student>(); Log.e("Pull---->", "start document"); break; case XmlPullParser.START_TAG: localName = xmlPullParser.getName(); if ("student".equals(xmlPullParser.getName())) { stu = new Student(); //将ID保存到stu中 stu.setId(Long.parseLong(xmlPullParser.getAttributeValue(0))); Log.e("Pull----->", stu.getId()+""); }else if(stu != null){ //声明一个变量用于存储节点文本 String currentData = null; if ("name".equals(xmlPullParser.getName())) { /* * 注意这里nextText()的使用:当前事件为START-TAG * 如果接下来是文本,就会返回当前的文本内容;如果下一个事件是End_TAG * 就会返回空字符串;否则抛出一个yichang */ currentData = xmlPullParser.nextText(); //存储name的信息 stu.setName(currentData); }else if("speciality".equals(xmlPullParser.getName())){ currentData = xmlPullParser.nextText(); //存储专业信息 stu.setSpeciality(currentData); }else if("qq".equals(xmlPullParser.getName())){ currentData = xmlPullParser.nextText(); //存储专业信息 stu.setQQ(Long.parseLong(currentData)); } } break; case XmlPullParser.END_TAG: localName = xmlPullParser.getName(); Log.e("Pull----->", localName); if ("student".equals(localName) && stu != null) { studnets.add(stu); stu = null; } break; default: break; } //解析下一事件 eventType = xmlPullParser.next(); } } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (XmlPullParserException e) { // TODO Auto-generated catch block e.printStackTrace(); } return studnets; }
这里也打印出log贴出来并做出了分析
总结:
SAX和PULL解析器虽然在代码上可能写的有些复杂,但是它们的解析效率,和思维逻辑的清晰都是非常好的,值得我们在软件开发中使用。
- Anroid开发之Xml的解析
- Anroid开发之Handler的使用方法
- Anroid开发 之 音频文件的循环播放
- anroid 之蓝牙开发
- Android开发之XML文件的解析
- Android开发之xml的解析
- Anroid开发之权限宝典
- anroid应用开发之会滚动的TextView
- iOS开发之XML解析
- android 开发之解析xml
- iOS开发之XML解析
- iOS开发之XML解析
- Android 开发之 XML 解析
- Unity3D开发之XML解析
- 【Bug记录】Anroid解析xml 出现unexpected token错误
- iOS开发之xml数据解析的基本流程
- Adroid开发之解析xml数据的两种方式
- Android开发之XML解析——SAX解析XML
- xUtils框架DBUtils数据库版本升级方案
- SAP HR模块的基础数据表和增强配置
- Linux 简单命令 随心记
- 几种排序方式
- 全国软件--微生物增殖
- Anroid开发之Xml的解析
- 【Android】信鸽推送通知栏点击之重复打开APP&重复从Laucher主入口启动问题
- Android 开发中遇到Read-only file system问题解决方案
- 在oracle sql 中处理日期大全
- NodeJS和Socket.IO搭建聊天室应用
- 预置SDcard资源
- Gradle依赖的统一管理
- SAP HR的使用心得
- Spring整合CXF,发布RSETful 风格WebService