Android 读取 XML 文件之 SAX 解析编码模板

news/2024/9/19 4:43:57/ 标签: android, xml, java, 安卓, android-studio, android studio
xmlns="http://www.w3.org/2000/svg" style="display: none;">

一、SAX 解析概述

  1. SAX(Simple API for XML)是一种基于事件的 XML 解析技术,它一边读取 XML 文件一边解析,占用内存少,适用于大型文件

  2. SAX 解析器会触发一系列事件,例如,开始解析元素、结束解析元素、遇到字符数据等,我们只需要实现对应的事件处理器来处理这些事件即可


二、SAX 解析基本使用

1、使用步骤
  1. 获取解析器实例
java">SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
  1. 实现对应的事件处理器
java">class MyHandler extends DefaultHandler {// 开始解析元素@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {super.startElement(uri, localName, qName, attributes);}// 遇到字符数据@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {super.characters(ch, start, length);}// 结束解析元素@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {super.endElement(uri, localName, qName);}
}
  1. 得到输入源,运行解析器
java">MyHandler myhandler = new MyHandler();
saxParser.parse(inputSource, myhandler);
2、演示
  1. user.xml,准备好 XML 文件,该文件放置在 res/raw 目录下,这样,在 Activity 中可通过 getResources().openRawResource() 获取到该目录下的资源
xml"><users><user><name>jack</name><age>21</age></user><user><name>tom</name><age>22</age></user>
</users>
  1. 事件处理器
java">class MyHandler extends DefaultHandler {public final String TAG = MyHandler.class.getSimpleName();@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {Log.i(TAG, "------------------------------ 开始标签:" + qName);}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {String str = new String(ch, start, length);Log.i(TAG, "------------------------------ 文本内容:" + str);}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {Log.i(TAG, "------------------------------ 结束标签:" + qName);}
}
  1. 测试代码
java">try {SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();SAXParser saxParser = saxParserFactory.newSAXParser();InputStream inputStream = getResources().openRawResource(R.raw.users);InputSource inputSource = new InputSource(inputStream);MyHandler myhandler = new MyHandler();saxParser.parse(inputSource, myhandler);
} catch (ParserConfigurationException | SAXException | IOException e) {e.printStackTrace();
}
  • 输出结果
I/MyHandler: ------------------------------ 开始标签:users
I/MyHandler: ------------------------------ 文本内容:
I/MyHandler: ------------------------------ 文本内容:    
I/MyHandler: ------------------------------ 开始标签:user
I/MyHandler: ------------------------------ 文本内容:
I/MyHandler: ------------------------------ 文本内容:        
I/MyHandler: ------------------------------ 开始标签:name
I/MyHandler: ------------------------------ 文本内容:jack
I/MyHandler: ------------------------------ 结束标签:name
I/MyHandler: ------------------------------ 文本内容:
I/MyHandler: ------------------------------ 文本内容:        
I/MyHandler: ------------------------------ 开始标签:age
I/MyHandler: ------------------------------ 文本内容:21
I/MyHandler: ------------------------------ 结束标签:age
I/MyHandler: ------------------------------ 文本内容:
I/MyHandler: ------------------------------ 文本内容:    
I/MyHandler: ------------------------------ 结束标签:user
I/MyHandler: ------------------------------ 文本内容:
I/MyHandler: ------------------------------ 文本内容:    
I/MyHandler: ------------------------------ 开始标签:user
I/MyHandler: ------------------------------ 文本内容:
I/MyHandler: ------------------------------ 文本内容:        
I/MyHandler: ------------------------------ 开始标签:name
I/MyHandler: ------------------------------ 文本内容:tom
I/MyHandler: ------------------------------ 结束标签:name
I/MyHandler: ------------------------------ 文本内容:
I/MyHandler: ------------------------------ 文本内容:        
I/MyHandler: ------------------------------ 开始标签:age
I/MyHandler: ------------------------------ 文本内容:22
I/MyHandler: ------------------------------ 结束标签:age
I/MyHandler: ------------------------------ 文本内容:
I/MyHandler: ------------------------------ 文本内容:    
I/MyHandler: ------------------------------ 结束标签:user
I/MyHandler: ------------------------------ 文本内容:
I/MyHandler: ------------------------------ 结束标签:users
3、演示优化
(1)优化思路
  1. 对于 <name>jack</name><age>21</age>,我们只关注标签之间的文本内容

  2. 当 startElement 方法被触发且 qName.equals("name") 时,我们已经到 name 开始标签

  3. 准备开始获取标签之间的文本内容

  4. 这个时候在 characters 方法中,即可获取到 name 标签之间的文本内容

  5. 当 endElement 方法被触发且 qName.equals("name") 时,我们已经到 name 结束标签

  6. 结束获取标签之间的文本内容

(2)具体实现
  • 测试代码,这次我们只关注标签之间的文本内容
java">class MyHandler extends DefaultHandler {public final String TAG = MyHandler.class.getSimpleName();private boolean getTextFlag = false;@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {if (qName.equals("name") || qName.equals("age")) {getTextFlag = true;Log.i(TAG, "-------------------- 开始标签:" + qName);} else if (qName.equals("user")) {Log.i(TAG, "------------------------------ 开始标签:" + qName);}}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {if (getTextFlag) {String str = new String(ch, start, length);Log.i(TAG, "---------- 文本内容:" + str);}}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {if (qName.equals("name") || qName.equals("age")) {getTextFlag = false;Log.i(TAG, "-------------------- 结束标签:" + qName);} else if (qName.equals("user")) {Log.i(TAG, "------------------------------ 结束标签:" + qName);}}
}
java">try {InputStream inputStream = getResources().openRawResource(R.raw.users);InputSource inputSource = new InputSource(inputStream);SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();SAXParser saxParser = saxParserFactory.newSAXParser();MyHandler myhandler = new MyHandler();saxParser.parse(inputSource, myhandler);
} catch (ParserConfigurationException | SAXException | IOException e) {e.printStackTrace();
}
  • 输出结果
I/MyHandler: ------------------------------ 开始标签:user
I/MyHandler: -------------------- 开始标签:name
I/MyHandler: ---------- 文本内容:jack
I/MyHandler: -------------------- 结束标签:name
I/MyHandler: -------------------- 开始标签:age
I/MyHandler: ---------- 文本内容:21
I/MyHandler: -------------------- 结束标签:age
I/MyHandler: ------------------------------ 结束标签:user
I/MyHandler: ------------------------------ 开始标签:user
I/MyHandler: -------------------- 开始标签:name
I/MyHandler: ---------- 文本内容:tom
I/MyHandler: -------------------- 结束标签:name
I/MyHandler: -------------------- 开始标签:age
I/MyHandler: ---------- 文本内容:22
I/MyHandler: -------------------- 结束标签:age
I/MyHandler: ------------------------------ 结束标签:user

三、SAX 解析实例实操

1、案例引入
  • 将如下的 XML 文件,希望将它解析成 2 个 User 对象,并放入 List<User> users 集合中
xml"><users><user><name>jack</name><age>21</age></user><user><name>tom</name><age>22</age></user>
</users>
2、案例思路
(1)创建 User 对象
  1. 当 startElement 方法被触发且 qName.equals("user") 时,我们已经到 user 开始标签

  2. 这个时候我们创建 User 对象

(2)获取 name
  1. 当 startElement 方法被触发且 qName.equals("name") 时,我们已经到 name 开始标签

  2. 准备开始获取 name 标签之间的文本内容

  3. 这个时候在 characters 方法中,即可获取到 name 标签之间的文本内容并传递给 User 对象

  4. 当 endElement 方法被触发且 qName.equals("name") 时,我们已经到 name 结束标签

  5. 结束获取 name 标签之间的文本内容

(3)获取 age
  1. 当 startElement 方法被触发且 qName.equals("age") 时,我们已经到 age 开始标签

  2. 准备开始获取 age 标签之间的文本内容

  3. 这个时候在 characters 方法中,即可获取到 age 标签之间的文本内容并传递给 User 对象

  4. 当 endElement 方法被触发且 qName.equals("age") 时,我们已经到 age 结束标签

  5. 结束获取 age 标签之间的文本内容

(4)保存 User 对象
  • 最后我们把 User 对象放入 users 集合中
3、具体实现
(1)Entity
java">public class User {private String name;private Integer age;public User() {}public User(String name, Integer age) {this.name = name;this.age = age;}public String getName() {return name;}public void setName(String name) {this.name = name;}public Integer getAge() {return age;}public void setAge(Integer age) {this.age = age;}@Overridepublic String toString() {return "User{" +"name='" + name + '\'' +", age=" + age +'}';}
}
(2)Test Code
java">class MyHandler extends DefaultHandler {public final String TAG = MyHandler.class.getSimpleName();private boolean getNameTextFlag = false;private boolean getAgeTextFlag = false;private List<User> users = new ArrayList<>();private User user = null;public List<User> getUsers() {return users;}@Overridepublic void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {if (qName.equals("user")) {user = new User();} else if (qName.equals("name")) {getNameTextFlag = true;} else if (qName.equals("age")) {getAgeTextFlag = true;}}@Overridepublic void characters(char[] ch, int start, int length) throws SAXException {String str = new String(ch, start, length);if (getNameTextFlag) {user.setName(str);} else if (getAgeTextFlag) {try {user.setAge(Integer.parseInt(str));} catch (NumberFormatException e) {e.printStackTrace();}}}@Overridepublic void endElement(String uri, String localName, String qName) throws SAXException {if (qName.equals("user")) {users.add(user);} else if (qName.equals("name")) {getNameTextFlag = false;} else if (qName.equals("age")) {getAgeTextFlag = false;}}
}
java">try {InputStream inputStream = getResources().openRawResource(R.raw.users);InputSource inputSource = new InputSource(inputStream);SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();SAXParser saxParser = saxParserFactory.newSAXParser();MyHandler myhandler = new MyHandler();saxParser.parse(inputSource, myhandler);List<User> users = myhandler.getUsers();for (User u : users) {Log.i(TAG, "---------- " + u);}
} catch (ParserConfigurationException | SAXException | IOException e) {e.printStackTrace();
}
  • 输出结果
I/GetXmlActivity: ---------- User{name='jack', age=21}
I/GetXmlActivity: ---------- User{name='tom', age=22}

http://www.ppmy.cn/news/1520926.html

相关文章

【微处理器系统原理和应用设计第六讲】片上微处理器系统系统架构

一、概念辨析 首先来厘清以下概念&#xff1a;微处理器&#xff0c;微控制器&#xff0c;单片机&#xff0c;片上微处理器系统 &#xff08;1&#xff09;微处理器&#xff1a;即MPU&#xff08;Microprocessor Unit&#xff09;&#xff0c;微处理器是一种计算机的中央处理单…

【Next】5. 全局权限管理

以下笔记来源&#xff1a;编程导航 需求 能够灵活配置每个页面所需要的用户权限&#xff0c;由全局权限管理系统自动校验和拦截路由&#xff0c;而不需要在每个页面中编写权限校验代码&#xff0c;提高开发效率。&#xff08;路由权限&#xff09;还要能够根据权限控制导航菜单…

生活因科技而美好:一键解锁PDF处理的无限可能

前言 “科技&#xff0c;是时代的诗篇&#xff0c;书写着人类不断超越自我、追求卓越的壮丽篇章。”这一理念深刻地影响着每一位开发者&#xff0c;他们不断探索、创新&#xff0c;旨在为用户带来更加便捷、高效的生活体验。正是在这样的背景下&#xff0c;一款旨在提升PDF处理…

MySQL case when【用法详解】

MySQL case when【用法详解】 语法1. 简单CASE表达式2. 搜索CASE表达式 示例示例1&#xff1a;使用简单CASE表达式示例2&#xff1a;使用搜索CASE表达式示例3&#xff1a;在UPDATE语句中使用CASE示例4&#xff1a;在DELETE语句中使用CASE注意事项 总结 在MySQL中&#xff0c;CA…

【技术解析】工厂内部导航系统:高精度定位与智能路径规划的技术实现

一、工厂内部导航系统概述 工厂内部导航系统集成了最新的GPS室内定位技术、蓝牙定位技术&#xff0c;实现了对工厂内部环境的无缝覆盖与高精度定位。无论是繁忙的生产线、错综复杂的仓库还是广阔的厂区&#xff0c;都能轻松应对。 二、工厂内部导航系统核心功能 实时定位&…

深度学习的发展历程

深度学习的起源 在机器学习中&#xff0c;我们经常使用两种方式来表示特征&#xff1a;局部表示&#xff08;Local Representation&#xff09;和分布式表示&#xff08;Distributed Representation&#xff09;。以颜色表示为例&#xff0c;见下图&#xff1a; 要学习到一种好…

电信500M宽带+AX210无线网卡测速

500M电信宽带&#xff0c;PC的Wifi模块是AX210 一、PC测速 2.4G Wifi 5G Wifi 有线网口 二、 手机端&#xff0c;小翼管家App测速 2.4G Wifi 5G Wifi 结论&#xff1a; 手机上网要快的话&#xff0c;还是要选择5G wifi

使用实例:xxl-job应用在spring cloud微服务下

1、首先下载&#xff0c;从github上下载&#xff0c;选择zip然后直接解压 https://github.com/xuxueli/xxl-job/releases 2、解压完后用idea启动。 启动这个启动类&#xff0c;然后按照路径访问 http://localhost:8080/xxl-job-admin/ 3、在你的项目里编写一个单独的微服务&a…

目标跟踪算法——ByteTrack算法原理解析

文章目录 ByteTrack1. ByteTrack算法步骤&#xff1a;2. 算法解释2.1 模型初始化2.2 模型更新算法流程2.2.1 检测结果划分&#xff0c;划分为高分和较低分段2.2.2 高分段处理手段2.2.3 最优匹配与未匹配划分2.2.4 低分框再匹配2.2.5 未确认轨迹处理2.2.6 更新状态 2.3 匈牙利匹…

ffplay源码分析(五)包缓存队列和帧缓存队列

在音视频处理流程中&#xff0c;ffplay的有两种队列&#xff0c;包缓存队列&#xff08;Packet Buffer Queue&#xff09;和帧缓存队列&#xff08;Frame Buffer Queue&#xff09;。这两个队列的存在&#xff0c;是为了适应音视频数据处理过程中的多线程架构——包括收包线程、…

图像白平衡

目录 效果 背景 什么是白平衡&#xff1f; 实现原理 将指定图色调调整为参考图色调主要流程 示例代码 效果 将图一效果转换为图二效果色调&#xff1a; 调整后&#xff0c;可实现色调对换 背景 现有两张图像&#xff0c;色调不一致&#xff0c;对于模型重建会有影响。因…

RabbitMQ 02 操作,配置信息,用户权限

01.介绍启动&#xff0c;关闭 02.环境 2.1 MQ是用Erlang语言写的 2.2 一个RabbitMQ 节点 一个 Erlang节点一个Erlang 程序 &#xff08;RabbitMQ程序&#xff09; 2.3 Erlang节点&#xff1a; 这个是Erlang节点集群状态下&#xff1a; 2.4 启动节点 2.5 查看日志信息 …

2021年大厂Java面试题(基础+框架+系统架构+分布式+实战)

Java线程的状态 进程和线程的区别&#xff0c;进程间如何通讯&#xff0c;线程间如何通讯 HashMap的数据结构是什么&#xff1f;如何实现的。和HashTable&#xff0c;ConcurrentHashMap的区别 Cookie和Session的区别 索引有什么用&#xff1f;如何建索引&#xff1f; Arra…

Elasticsearch 中,term 查询和 match 查询的区别

文章目录 前言Elasticsearch 中&#xff0c;term 查询和 match 查询的区别1. Term 查询2. Match 查询3. 总结 前言 如果您觉得有用的话&#xff0c;记得给博主点个赞&#xff0c;评论&#xff0c;收藏一键三连啊&#xff0c;写作不易啊^ _ ^。   而且听说点赞的人每天的运气都…

各种各样的正则表达式

一、校验数字的表达式 数字:^[0-9]*$ n位的数字:^\d{n}$ 至少n位的数字:^\d{n,}$ m-n位的数字:^\d{m,n}$ 零和非零开头的数字:^(0|[1-9][0-9]*)$ 非零开头的最多带两位小数的数字:^([1-9][0-9]*)+(.[0-9]{1,2})?$ 带1-2位小数的正数或负数:^(\-)?\d+(\.\d{1,2})?$ 正…

【flask】python框架flask的hello world

创建一个py文件&#xff0c;写如下内容 # save this as app.py from flask import Flaskapp Flask(__name__)app.route("/") def hello():return "Hello, World!"如下图 在此py文件路径下启动cmd&#xff0c;输入 flask run结果如下图 在浏览器中访问…

【科普】数字化和数字化转型:是什么,为什么,怎么做?

​一、什么是数字化转型&#xff1f; 近年来 “数字化”、“数字化转型”概念已经渗透到各个行业&#xff0c;成为业界的热点议题。对于什么是“数字化转型”&#xff0c;众说纷纭。 有人说“数字化转型不过就是给传统的信息化穿上皇帝的新衣”&#xff0c;也有人说“数字化转…

策略优化:提升MySQL数据备份效率的实用指南

在当今数据驱动的商业环境中&#xff0c;数据备份策略的优化对于确保数据安全和业务连续性至关重要。MySQL作为广泛使用的数据库系统&#xff0c;其数据备份策略的优化不仅可以提高数据恢复的效率&#xff0c;还能降低存储成本和提高系统性能。本文将深入探讨如何在MySQL中实现…

用户管理和授权

授权 mysql> show databases; -------------------- | Database | -------------------- | information_schema | | day01db | | employees | | mysql | | mysql01 | | mysql02 | | performance_schema …

深入理解Java虚拟机的类加载机制

深入理解Java虚拟机的类加载机制 目录 深入理解Java虚拟机的类加载机制 一、类加载概念与过程 1. 类加载定义与作用 2. 类加载过程详解 二、类加载器 1. 系统提供的类加载器 2. 自定义类加载器 三、双亲委派模型 1. 双亲委派模型的概念 2. 工作过程 四、类的卸载与重…