热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

AndroidSAX解析XML文档Android学习之路

SAX解析XML最近用到了XML数据,今天分享一下我对SAX的理解原理实例自定义Handler继承DefaultHandlerHandler执行顺序各方法参数讲解Sa

SAX解析XML


最近用到了XML数据 ,今天分享一下我对SAX的理解



  • 原理
  • 实例
    • 自定义Handler 继承DefaultHandler
    • Handler执行顺序各方法参数讲解
    • SaxParse的创建
    • 设置解析内容 开始解析

原理


sax 是基于事件驱动。那么什么是事件驱动呢(请自行百度)简单点说 就是触发一个事件 去执行某些操作;
sax在解析XML时 是边读取边解析,不会将整个文档加载到内存中。而是读到一个元素解析一个元素,和上下的元素是关联不上的,占用内存较小。这也是非常适合Android这种内存较小的嵌入式设备内存的原因;
sax在读取文档的时候激活一系列的事件并执行一些操作。
在开始读取文档的时候触发 startDocument() ;
读取到一个元素触发 startElement();
读取文本 触发characters(); ps:即使是读取到换行符也会触发
元素读取完毕 触发 endElement();
读取完整个文档触发 endDocument();
上述事件 基本就把xml文档读取完毕了,这些方法在DefaultHandle中已经封装好了,我们做的就是重写这些方法就可以了



贴代码


student XML文件



<Students><Student id&#61;"0"><name>张三name><clazz>13班clazz><age>17age>Student>
Students>

创建 StudentHandler 继承自 DefaultHandler


package com.skymxc.demo.parsexml;import android.text.TextUtils;
import android.util.Log;import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;import java.util.ArrayList;
import java.util.List;/*** Created by sky-mxc*/
public class StudentHandler extends DefaultHandler {private List students;private Student student;private String tag; //记录读取到的元素的名字&#64;Overridepublic void startDocument() throws SAXException {Log.e("Tag","&#61;&#61;&#61;&#61;&#61;&#61;&#61;startDocument()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;");students &#61; new ArrayList<>();}&#64;Overridepublic void endDocument() throws SAXException {super.endDocument();Log.e("Tag","&#61;&#61;&#61;&#61;&#61;&#61;&#61;endDocument()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;");}/**** &#64;param uri 明明空间的uri* &#64;param localName 不带前缀的元素名字* &#64;param qName 带有前缀的元素名* &#64;param attributes 属性* &#64;throws SAXException*/&#64;Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {Log.e("Tag","&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;startElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;"&#43;localName);Log.e("Tag","&#61;&#61;&#61;startElement():uri&#61;&#61;&#61;&#61;&#61;&#61;"&#43;uri);Log.e("Tag","&#61;&#61;&#61;startElement():localName&#61;&#61;&#61;&#61;&#61;&#61;"&#43;localName);Log.e("Tag","&#61;&#61;&#61;startElement():qName&#61;&#61;&#61;&#61;&#61;&#61;"&#43;qName);switch (localName){case "Student": //student元素student &#61; new Student();int id &#61; Integer.parseInt(attributes.getValue("id")); //获取到属性id的值student.setId(id);break;default:tag&#61;localName;//除了 student元素 其他元素都要读取文本 characters()无法获取元素名字break;}}&#64;Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {super.endElement(uri, localName, qName);Log.e("Tag","&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;endElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;"&#43;localName);switch (localName){case "Student":students.add(student);break;}}&#64;Overridepublic void characters(char[] ch, int start, int length) throws SAXException {Log.e("Tag","&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;");Log.e("Tag","&#61;&#61;&#61;&#61;&#61;&#61;start:"&#43;start);Log.e("Tag","&#61;&#61;&#61;&#61;&#61;&#61;length:"&#43;length);//将字符转为字符串String text &#61; new String(ch,start,length).trim();Log.e("Tag","&#61;&#61;&#61;&#61;当前元素:"&#43;tag&#43;"&#61;&#61;&#61;文本值&#xff1a;"&#43;text);//排除无效字符 会读取到一些换行符if (TextUtils.isEmpty(text)) return;if (student &#61;&#61; null) return;switch (tag){case "name":student.setName(text);break;case "age":int age &#61; Integer.parseInt(text);student.setAge(age);break;case "clazz":student.setClazz(text);break;}}public List getStudents() {return students;}
}

Handler中的执行过程解析 读取过程如下&#xff0c;可以看出 就算根节点没有文本也触发了characters() 因为会读取换行符 所以慎重处理


E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;startDocument()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;startElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;Students
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;startElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;Student
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;startElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;name
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;endElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;name
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;startElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;clazz
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;endElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;clazz
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;startElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;age
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;endElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;age
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;endElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;Student
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;endElement()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;Students
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;endDocument()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;

startElement() 参数如下 xml 文件中并没有定义 命名空间 和任何前缀
uri &#xff1a;为空
qName &#xff1a;也是元素的名字并没有带有前缀
localName&#xff1a; 当前元素的名字


E/Tag: &#61;&#61;&#61;startElement():uri&#61;&#61;&#61;&#61;&#61;&#61;
E/Tag: &#61;&#61;&#61;startElement():localName&#61;&#61;&#61;&#61;&#61;&#61;Student
E/Tag: &#61;&#61;&#61;startElement():qName&#61;&#61;&#61;&#61;&#61;&#61;Student
E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;

characters()参数如下
start :开始下标
length &#xff1a;长度


E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;characters()&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;&#61;E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;start:0E/Tag: &#61;&#61;&#61;&#61;&#61;&#61;length:3E/Tag: &#61;&#61;&#61;&#61;当前元素:clazz&#61;&#61;&#61;文本值&#xff1a;13班

创建SAXParse 设置解析内容


SAXParserFactory factory &#61; SAXParserFactory.newInstance();StudentHandler handler &#61; new StudentHandler();try {SAXParser parser &#61; factory.newSAXParser();parser.parse(getAssets().open("students.xml"),handler);Log.e("Tag","&#61;&#61;&#61;Size:"&#43;handler.getStudents().size());for (Student stu :handler.getStudents()){Log.e("Tag","&#61;&#61;Name:"&#43;stu.getName()&#43;"&#61;&#61;&#61;Age:"&#43;stu.getAge()&#43;"&#61;&#61;&#61;&#61;Clazz:"&#43;stu.getClazz()&#43;"&#61;&#61;id:"&#43;stu.getId());}} catch (ParserConfigurationException e) {e.printStackTrace();} catch (SAXException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}

读取结果


E/Tag: &#61;&#61;Name:张三&#61;&#61;&#61;Age:17&#61;&#61;&#61;&#61;Clazz:13班&#61;&#61;id:0

对于SAX的理解就这些了
为什么只有深夜 才有感觉呢&#xff0c;唉…..发愁

github地址 &#xff1a;https://github.com/sky-mxc/AndroidDemo/tree/master/parsexml



推荐阅读
  • Spring源码解密之默认标签的解析方式分析
    本文分析了Spring源码解密中默认标签的解析方式。通过对命名空间的判断,区分默认命名空间和自定义命名空间,并采用不同的解析方式。其中,bean标签的解析最为复杂和重要。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • C语言注释工具及快捷键,删除C语言注释工具的实现思路
    本文介绍了C语言中注释的两种方式以及注释的作用,提供了删除C语言注释的工具实现思路,并分享了C语言中注释的快捷键操作方法。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • 本文讨论了一个关于cuowu类的问题,作者在使用cuowu类时遇到了错误提示和使用AdjustmentListener的问题。文章提供了16个解决方案,并给出了两个可能导致错误的原因。 ... [详细]
  • 本文介绍了Android 7的学习笔记总结,包括最新的移动架构视频、大厂安卓面试真题和项目实战源码讲义。同时还分享了开源的完整内容,并提醒读者在使用FileProvider适配时要注意不同模块的AndroidManfiest.xml中配置的xml文件名必须不同,否则会出现问题。 ... [详细]
  • Go Cobra命令行工具入门教程
    本文介绍了Go语言实现的命令行工具Cobra的基本概念、安装方法和入门实践。Cobra被广泛应用于各种项目中,如Kubernetes、Hugo和Github CLI等。通过使用Cobra,我们可以快速创建命令行工具,适用于写测试脚本和各种服务的Admin CLI。文章还通过一个简单的demo演示了Cobra的使用方法。 ... [详细]
  • 本文介绍了如何使用C#制作Java+Mysql+Tomcat环境安装程序,实现一键式安装。通过将JDK、Mysql、Tomcat三者制作成一个安装包,解决了客户在安装软件时的复杂配置和繁琐问题,便于管理软件版本和系统集成。具体步骤包括配置JDK环境变量和安装Mysql服务,其中使用了MySQL Server 5.5社区版和my.ini文件。安装方法为通过命令行将目录转到mysql的bin目录下,执行mysqld --install MySQL5命令。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 开发笔记:实验7的文件读写操作
    本文介绍了使用C++的ofstream和ifstream类进行文件读写操作的方法,包括创建文件、写入文件和读取文件的过程。同时还介绍了如何判断文件是否成功打开和关闭文件的方法。通过本文的学习,读者可以了解如何在C++中进行文件读写操作。 ... [详细]
  • VScode格式化文档换行或不换行的设置方法
    本文介绍了在VScode中设置格式化文档换行或不换行的方法,包括使用插件和修改settings.json文件的内容。详细步骤为:找到settings.json文件,将其中的代码替换为指定的代码。 ... [详细]
  • 本文介绍了一个Java猜拳小游戏的代码,通过使用Scanner类获取用户输入的拳的数字,并随机生成计算机的拳,然后判断胜负。该游戏可以选择剪刀、石头、布三种拳,通过比较两者的拳来决定胜负。 ... [详细]
  • switch语句的一些用法及注意事项
    本文介绍了使用switch语句时的一些用法和注意事项,包括如何实现"fall through"、default语句的作用、在case语句中定义变量时可能出现的问题以及解决方法。同时也提到了C#严格控制switch分支不允许贯穿的规定。通过本文的介绍,读者可以更好地理解和使用switch语句。 ... [详细]
  • 有没有一种方法可以在不继承UIAlertController的子类或不涉及UIAlertActions的情况下 ... [详细]
author-avatar
遗忘的vbnv
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有