Android SAX解析XML文档 -- Android 学习之路

SAX解析XML

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

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

原理

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

贴代码

student XML文件

<?xml version="1.0" encoding="utf-8"?>
<Students>
        <Student id="0">
            <name>张三</name>
            <clazz>13班</clazz>
            <age>17</age>
        </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<Student> students;
    private Student student;
    private String tag;     //记录读取到的元素的名字



    @Override
    public void startDocument() throws SAXException {
        Log.e("Tag","=======startDocument()========");
        students = new ArrayList<>();
    }

    @Override
    public void endDocument() throws SAXException {
        super.endDocument();
        Log.e("Tag","=======endDocument()========");
    }

    /**
     *
     * @param uri 明明空间的uri
     * @param localName 不带前缀的元素名字
     * @param qName 带有前缀的元素名
     * @param attributes 属性
     * @throws SAXException
     */
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        Log.e("Tag","==========startElement()==========="+localName);
        Log.e("Tag","===startElement():uri======"+uri);
        Log.e("Tag","===startElement():localName======"+localName);
        Log.e("Tag","===startElement():qName======"+qName);

        switch (localName){
            case "Student":         //student元素
                student = new Student();
                int id = Integer.parseInt(attributes.getValue("id"));   //获取到属性id的值
                student.setId(id);
                break;
            default:
                tag=localName;//除了 student元素 其他元素都要读取文本 characters()无法获取元素名字
                break;
        }

    }

    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        super.endElement(uri, localName, qName);
        Log.e("Tag","==========endElement()==========="+localName);
        switch (localName){
            case "Student":
                students.add(student);
                break;
        }
    }

    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        Log.e("Tag","==========characters()===========");
        Log.e("Tag","======start:"+start);
        Log.e("Tag","======length:"+length);

        //将字符转为字符串
        String text = new String(ch,start,length).trim();
        Log.e("Tag","====当前元素:"+tag+"===文本值:"+text);
        //排除无效字符 会读取到一些换行符
        if (TextUtils.isEmpty(text)) return;
        if (student == null) return;
        switch (tag){
            case "name":
                student.setName(text);
                break;
            case "age":
                int age = Integer.parseInt(text);
                student.setAge(age);
                break;
            case "clazz":
                student.setClazz(text);
                break;
        }
    }

    public List<Student> getStudents() {
        return students;
    }
}

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

E/Tag: =======startDocument()========
E/Tag: ==========startElement()===========Students
E/Tag: ==========characters()===========
E/Tag: ==========characters()===========
E/Tag: ==========startElement()===========Student
E/Tag: ==========characters()===========
E/Tag: ==========characters()===========
E/Tag: ==========startElement()===========name
E/Tag: ==========characters()===========
E/Tag: ==========endElement()===========name
E/Tag: ==========characters()===========
E/Tag: ==========characters()===========
E/Tag: ==========startElement()===========clazz
E/Tag: ==========characters()===========
E/Tag: ==========endElement()===========clazz
E/Tag: ==========characters()===========
E/Tag: ==========characters()===========
E/Tag: ==========startElement()===========age
E/Tag: ==========characters()===========
E/Tag: ==========endElement()===========age
E/Tag: ==========characters()===========
E/Tag: ==========characters()===========
E/Tag: ==========endElement()===========Student
E/Tag: ==========characters()===========
E/Tag: ==========endElement()===========Students
E/Tag: =======endDocument()========

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

E/Tag: ===startElement():uri======
E/Tag: ===startElement():localName======Student
E/Tag: ===startElement():qName======Student
E/Tag: ==========characters()===========

characters()参数如下
start :开始下标
length :长度

 E/Tag: ==========characters()===========
 E/Tag: ======start:0
 E/Tag: ======length:3
 E/Tag: ====当前元素:clazz===文本值:13班

创建SAXParse 设置解析内容

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

读取结果

 E/Tag: ==Name:张三===Age:17====Clazz:13班==id:0

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

github地址 :https://github.com/sky-mxc/AndroidDemo/tree/master/parsexml

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

佛系编码i

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值