首页 > 其他分享 >Android 读取 XML 文件之 SAX 解析编码模板

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

时间:2024-09-01 08:54:09浏览次数:14  
标签:XML String ------------------------------ 标签 qName name SAX Android MyHandler

一、SAX 解析概述

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

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


二、SAX 解析基本使用

1、使用步骤
  1. 获取解析器实例
SAXParserFactory saxParserFactory = SAXParserFactory.newInstance();
SAXParser saxParser = saxParserFactory.newSAXParser();
  1. 实现对应的事件处理器
class MyHandler extends DefaultHandler {

    // 开始解析元素
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        super.startElement(uri, localName, qName, attributes);
    }

    // 遇到字符数据
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        super.characters(ch, start, length);
    }

    // 结束解析元素
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
    }
}
  1. 得到输入源,运行解析器
MyHandler myhandler = new MyHandler();
saxParser.parse(inputSource, myhandler);
2、演示
  1. user.xml,准备好 XML 文件,该文件放置在 res/raw 目录下,这样,在 Activity 中可通过 getResources().openRawResource() 获取到该目录下的资源
<users>
    <user>
        <name>jack</name>
        <age>21</age>
    </user>
    <user>
        <name>tom</name>
        <age>22</age>
    </user>
</users>
  1. 事件处理器
class MyHandler extends DefaultHandler {
    public final String TAG = MyHandler.class.getSimpleName();

    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        Log.i(TAG, "------------------------------ 开始标签:" + qName);
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String str = new String(ch, start, length);
        Log.i(TAG, "------------------------------ 文本内容:" + str);
    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        Log.i(TAG, "------------------------------ 结束标签:" + qName);
    }
}
  1. 测试代码
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)具体实现
  • 测试代码,这次我们只关注标签之间的文本内容
class MyHandler extends DefaultHandler {
    public final String TAG = MyHandler.class.getSimpleName();

    private boolean getTextFlag = false;

    @Override
    public 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);
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        if (getTextFlag) {
            String str = new String(ch, start, length);
            Log.i(TAG, "---------- 文本内容:" + str);
        }
    }

    @Override
    public 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);
        }
    }
}
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 集合中
<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
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;
    }

    @Override
    public String toString() {
        return "User{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
(2)Test Code
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;
    }

    @Override
    public 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;
        }
    }

    @Override
    public 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();
            }
        }
    }

    @Override
    public 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;
        }
    }
}
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}

标签:XML,String,------------------------------,标签,qName,name,SAX,Android,MyHandler
From: https://blog.csdn.net/weixin_52173250/article/details/141774078

相关文章

  • 【Android】根据URI获取文件扩展名或MimeType
    关于安卓中的URI安卓中的URI包含多种格式,可以是文件,可以是媒体库资源,可以是Resource也可以是网络地址,或其它资源标识这里我们主要针对文件来源的URI安卓中通过URI访问文件主要包括三种方式文件路径媒体库资源(背后仍然是文件,但无法直接访问)Resource资源对于这三种不同......
  • Android开发 - ClassLoader 加载外部类解析
    ClassLoader是什么ClassLoader主要作用是将字节码文件(.class文件)加载到Java虚拟机(JVM)中,以便应用程序可以使用这些类ClassLoader的好处模块化加载:应用程序可能由多个模块组成,而这些模块可能需要按需加载插件机制:很多应用支持插件化,插件在安装或更新后需要动态加载......
  • 基于live555开发的多线程RTSPServer轻量级流媒体服务器EasyRTSPServer开源代码及其调
    EasyRTSPServer参考live555testProg中的testOnDemandRTSPServer示例程序,将一个live555testOnDemandRTSPServer封装在一个类中,例如,我们称为ClassEasyRTSPServer,在EasyRTSPServer_Create接口调用时,我们新建一个EasyRTSPServer对象,再通过调用EasyRTSPServer_Startup接口,将EasyRTSP......
  • 基于ssm+vue基于Android的大学校园车辆管理系统前【开题+程序+论文】
    本系统(程序+源码)带文档lw万字以上 文末可获取一份本项目的java源码和数据库参考。系统程序文件列表开题报告内容研究背景随着高校规模的不断扩大和师生人数的持续增长,大学校园内的车辆管理成为了一个日益严峻的问题。传统的人工管理方式不仅效率低下,而且难以应对日益复杂......
  • Android源码bta_gattc_start_discover剖析
    1.前言当BLE设备作为GATT客户端(GATTClient)连接到GATT服务器(GATTServer)后,它通常需要执行发现过程以了解服务器的GATT数据库结构。这包括服务(Services)、特征(Characteristics)和描述符等。bta_gattc_start_discover 函数正是用于启动这一过程的。2.工作流程连接建立:首先,GAT......
  • Android系统给所有apk默认权限
        Android系统的定制开发中,经常会有客户要求赋予他们提供的应用程序(APK)所默认的所有权限;百度上有多种版本可以给与默认权限,但是经过博主试验,都是比较复杂麻烦的操作;在这里博主给出一个简单方便方法,直接上代码;---a/frameworks/base/services/core/java/com/android/......
  • PbootCMS生成的sitemap.xml中增加tag标签链接
    打开/apps/home/model/SitemapModel.php,在78行后面增加个指定分类标签调用代码。//指定分类标签调用publicfunctiongetSortTags($scode){$join=array(array('ay_content_sortb','a.scode=b.scode','LEFT'......
  • 在Android开发中,如何使用SharedPreferences(简称SP)一个轻量级的数据存储方式
    目录全局SharedPreferences工具类代码说明:如何使用这个工具类?在Android开发中,SharedPreferences(简称SP)是一个轻量级的数据存储方式,常用于保存应用的配置信息或少量的数据。为了便于在全局使用,可以将其封装到一个工具类中。以下是一个带有详细中文注释的全局SharedPrefere......
  • Android的UI设计与布局
    目录Android布局系统概述常见的布局控件常见UI组件自适应布局和屏幕适配主题和样式 总结在Android中,UI设计与布局是开发过程中非常重要的一部分,直接决定了用户与应用的交互体验。Android提供了多种布局控件和UI组件,帮助开发者设计出不同风格和功能的界面。A......
  • Android 11 About SleepToken / (Settings)Screen timeout
    AndroidR激活Settings里面的息屏休眠,最前台运行的Activity生命周期->onPause->onStopadbshelldumpsyswindowpolicy//获取PhoneWindowManager的dump信息...bootCompleted=truescreenState=SCREEN_STATE_ON/SCREEN_STATE_OFFinteractiveState=INTERACTIVE_STATE_AW......