Android XML SAX 数据解析

SAX 是一个解析速度快而且占用内存少的 XML 解析器,非常适合用于 Android 等资源紧张的移动设备

SAX 解析 XML 文件采用的是事件驱动, 也就是不需要先解析整个文档,而是在解析文档过程中,判断读到的字符是否匹配 XML 语法的某一部分 (文档开头,文档结束,标签开头,变迁结束等),如果匹配的话,就会触发相应的事件,这些事件都定义在 ContentHandler 接口中

ContentHandler

ContentHandler 默认需要实现类重写以下几个方法

方法 说明
void characters(char[] ch, int start, int length) 读到内容时回调该方法
ch 用于存放该文档的内容
start / end 是当前内容在文档内容中的起始和结束位置
void endDocument() 读到文档结束标志时触发,在这里可以完成一些收尾工作
void endElement(String uri, String localName, String qName) 遇到结束标签的时候调用该方法
void endPrefixMapping(String prefix) 结束命名空间映射的范围时触发
void ignorableWhitespace(char[] ch, int start, int length) 读到可以忽略的空白时会回调该方法
void processingInstruction(String target, String data) 读到处理指令时回调
void setDocumentLocator(Locator locator) 接收一个对象以查找 SAX 文档事件的来源
void skippedEntity(String name) 遇到可跳过 Entity 时触发
void startDocument() 读到文档开始标志时触发,在这里可以完成一些初始化工作
void startElement(String uri, String localName, String qName, Attributes atts) 遇到标签开始时回调,参数依次为命名空间,带命名控件的标签名,不带命名空间的标签名,所有属性
void startPrefixMapping(String prefix, String uri) 遇到命名空间映射的范围时触发

跟其它 Android 中的接口一样,如果自己实现 ContentHandler 就有一大堆的方法需要重写,还好, Android 了解这一点,已经帮我们默认实现了一个 DefaultHandler ,我们只需要继承它然后重写需要的方法即可

注意: 节点之间的空白文本也是文本节点,解析的时候也会走这些节点

使用 SAX 解析 XML 的一般流程

  1. 获取文件资源建立输入流对象

    InputStream is = getAssets().open("languages.xml");
    
  2. 自定义个一个 ContentHandler 继承 DefaultHandler 重写需要的方法

    public class SaxHelper extends DefaultHandler{}
    
  3. 创建 XML 解析处理器

    SaxHelper ss = new SaxHelper();
    
  4. 创建一个 SAX 解析器工厂实例

    SAXParserFactory factory = SAXParserFactory.newInstance();
    
  5. 通过 SAX 解析起工厂创建一个 SAX 解析器对象

    SAXParser parser = factory.newSAXParser();
    
  6. 将 xml 解析处理器分配给解析器,对文档进行解析,将事件发送给处理器

    parser.parse(is, ss);
    

范例

  1. 创建一个 空的 Android 项目 cn.twle.android.SaxParser

  2. app 上点右键,选择 Folder - Assets Folder 创建 assets 目录,并在 assets 目录下新建文件 languages.xml ,内容如下

    <?xml version="1.0" encoding="utf-8" ?>
    <languages>
        <language id="1">
            <name>Java</name>
            <rank>1</rank>
        </language>
        <language id="2">
            <name>C</name>
            <rank>2</rank>
        </language>
        <language id="3">
            <name>C++</name>
            <rank>3</rank>
        </language>
    </languages>
    
  3. 修改 activity_main.xml

    <?xml version="1.0" encoding="utf-8" ?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:padding="8dp"
        android:orientation="vertical" >
    
        <Button
            android:text="解析"
            android:id="@+id/btn_parser"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content" />
    
        <TextView
            android:id="@+id/ms_dst"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="" />
    </LinearLayout>
    
  4. 创建一个 POJO 业务类 Language.java

    package cn.twle.android.saxparser;
    
    public class Language {
        private int id;
        private String name;
        private String rank;
    
        public Language() {
        }
    
        public void setId(int id) {
            this.id = id;
        }
    
        public int getId() {
            return this.id;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public String getName() {
            return this.name;
        }
    
        public void setRank(String rank) {
            this.rank = rank;
        }
    
        public String getRank() {
            return this.rank;
        }
    }
    
  5. 创建一个 SAX 解析帮助类 SaxHelper.java

    package cn.twle.android.saxparser;
    
    import org.xml.sax.Attributes;
    import org.xml.sax.SAXException;
    import org.xml.sax.helpers.DefaultHandler;
    
    import java.util.ArrayList;
    
    public class SaxHelper extends DefaultHandler {
    
        private Language language;
        private ArrayList<Language> languages;
    
        //当前解析的元素标签
        private String tagName = null;
    
        /**
         * 当读取到文档开始标志是触发,通常在这里完成一些初始化操作
         */
        @Override
        public void startDocument() throws SAXException {
            this.languages = new ArrayList<Language>();
        }
    
        /**
         * 读到一个开始标签时调用,第二个参数为标签名,最后一个参数为属性数组
         */
        @Override
        public void startElement(String uri, String localName, String qName,
                                 Attributes attributes) throws SAXException {
            if (localName.equals("language")) {
                language = new Language();
                language.setId(Integer.parseInt(attributes.getValue("id")));
            }
            this.tagName = localName;
        }
    
        /**
         * 读到到内容,第一个参数为字符串内容,后面依次为起始位置与长度
         */
    
        @Override
        public void characters(char[] ch, int start, int length)
                throws SAXException {
            //判断当前标签是否有效
            if (this.tagName != null) {
                String data = new String(ch, start, length);
                //读取标签中的内容
                if (this.tagName.equals("name")) {
                    this.language.setName(data);
                } else if (this.tagName.equals("rank")) {
                    this.language.setRank(data);
                }
    
            }
    
        }
    
        /**
         * 处理元素结束时触发,这里将对象添加到结合中
         */
        @Override
        public void endElement(String uri, String localName, String qName)
                throws SAXException {
            if (localName.equals("language")) {
                this.languages.add(language);
                language = null;
            }
            this.tagName = null;
        }
    
        //获取persons集合
        public ArrayList<Language> getData() {
            return languages;
        }
    
    }
    
  6. 修改 MainActivity.java

    package cn.twle.android.saxparser;
    
    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    
    import java.io.InputStream;
    import java.util.ArrayList;
    
    import javax.xml.parsers.SAXParser;
    import javax.xml.parsers.SAXParserFactory;
    
    public class MainActivity extends AppCompatActivity{
    
        private TextView ms_dst;
    
        private Button btn_parser;
    
        private ArrayList<Language> languages;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            ms_dst = findViewById(R.id.ms_dst);
    
            languages = new ArrayList<Language>();
    
            btn_parser = findViewById(R.id.btn_parser);
            btn_parser.setOnClickListener(new View.OnClickListener() {
    
                @Override
                public void onClick(View v) {
    
                    //获取文件资源建立输入流对象
                    try {
    
                        InputStream is = getAssets().open("languages.xml");
                        SaxHelper   saxHelper = new SaxHelper();
                        SAXParserFactory factory = SAXParserFactory.newInstance();
                        SAXParser parser = factory.newSAXParser();
                        parser.parse(is, saxHelper);
    
                        languages = saxHelper.getData();
                        is.close();
    
                        if (languages.equals(null)) {
                            ms_dst.setText("解析失败");
                        }
    
                        StringBuilder sb2 = new StringBuilder();
    
                        for (Language p1 : languages) {
                            sb2.append(p1.getId() + ". " + p1.getName() + "的排名是:" + p1.getRank() + "\n");
                        }
    
                        ms_dst.setText(sb2.toString());
    
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
    
                }
            });
        }
    }
    

Android 基础教程

关于   |   FAQ   |   我们的愿景   |   广告投放   |  博客

  简单教程,简单编程 - IT 入门首选站

Copyright © 2013-2022 简单教程 twle.cn All Rights Reserved.