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

来源:互联网 发布:数据库考点总结 编辑:程序博客网 时间:2024/05/03 10:26

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()===========StudentsE/Tag: ==========characters()===========E/Tag: ==========characters()===========E/Tag: ==========startElement()===========StudentE/Tag: ==========characters()===========E/Tag: ==========characters()===========E/Tag: ==========startElement()===========nameE/Tag: ==========characters()===========E/Tag: ==========endElement()===========nameE/Tag: ==========characters()===========E/Tag: ==========characters()===========E/Tag: ==========startElement()===========clazzE/Tag: ==========characters()===========E/Tag: ==========endElement()===========clazzE/Tag: ==========characters()===========E/Tag: ==========characters()===========E/Tag: ==========startElement()===========ageE/Tag: ==========characters()===========E/Tag: ==========endElement()===========ageE/Tag: ==========characters()===========E/Tag: ==========characters()===========E/Tag: ==========endElement()===========StudentE/Tag: ==========characters()===========E/Tag: ==========endElement()===========StudentsE/Tag: =======endDocument()========

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

E/Tag: ===startElement():uri======E/Tag: ===startElement():localName======StudentE/Tag: ===startElement():qName======StudentE/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

0 0