文档章节

Anroid开发之Xml的解析

YH_猿员猿
 YH_猿员猿
发布于 2016/07/21 17:31
字数 1719
阅读 2
收藏 0
点赞 0
评论 0
    在前面的一个博客中我们了解了json数据的解析,现在我们来实现对xml格式的数据的解析,xml是一种可扩展标记语言,是由标签组成的。方便我们读取数据。
    xml的解析有三种方式,DOM解析,SAX解析,PULL解析。

  1. DOM解析XML文件时,会将XML文件所有内容都读取到内存中,然后再遍历XML文件树,检索需要的数据。DOM解析XML有很大的缺陷,对内存的消耗比较大,影响系统的性能,所以我这里没有详细讲DOM解析。
  2. SAX解析是一种占用内存少,且解析速度快的解析器,它采用事件驱动,它不需要解析整个文档,而是按照顺序,检索XML文件是否符合XML的语法,当符合时会触发相应的回调函数。这些函数是在ContentHander中,我们可以重写这些方法来实现我们对数据的解析。
  3. Pull解析是一种可以解析部分XML文件的解析方式,当我们只需要XML文件中的一部分数据时,用这种方法是非常好的。Pull解析和SAX解析类似,SAX解析器工作方式是自动的将事件推入注册的事件处理器进行处理,因此你不能控制事件的处理主动结束,而Pull解析的工作方式为允许你的应用程序代码主动从解析器获取事件,因此我们可以在获取了我们需要的数据时,主动结束解析。

SAX解析
SAX解析的主要是重写ContentHander中回调方法,在其中主要的是:

  1. startDocument:当遇到文档时候触发事件。
  2. startElement:当遇到开始标签时触发。
  3. endElement:当遇到结束标签时触发。
  4. characters:当遇到xml内容时触发。
    这里写图片描述

上面是我自己建的一个xml文件,命名为students.xml,并将它放在assets文件夹下。

1.我首先定义了一个student类对象,用来存放解析出来的xml数据

public class Student {

    private Long Id;
    private String Name;
    private String Speciality;
    private Long QQ;
    public Student() {
    }
    //省略了get和set方法
}

2.实例化一个SAX工厂,并获取SAX解析器,读取xml文件,创建回调函数

protected List<Student> parserXML() {
        //实例化一个SAX解析工厂
        SAXParserFactory factory = SAXParserFactory.newInstance();
        List<Student> studnets = null;
        //获取XML解析器
        try {
            XMLReader reader = factory.newSAXParser().getXMLReader();
            studnets = new ArrayList<Student>();
            //设置回调函数,这里是我自定义的回调函数
            reader.setContentHandler(new StudentHander(studnets));
            //读取Assets下的student.xml文件
            reader.parse(new InputSource(SAXXMLActivity.this.
                    getResources().getAssets().open("students.xml")));
        } catch (SAXException e) {
            e.printStackTrace();
        } catch (ParserConfigurationException e) {
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

        return studnets;

3.自定义StudentHander回调函数,继承自DefaultHander;在回调方法里解析出自己需要的数据。其中preTAG用来存储当前节点名称,在endElement中要记得滞空。

public class StudentHander extends DefaultHandler {
    private String preTAG;
    private List<Student> ListStudent;
    private Student stu;
    public StudentHander() {
    }

    public StudentHander(List<Student> listStudent) {
        super();
        ListStudent = listStudent;
    }


    //开始解析文档
    @Override
    public void startDocument() throws SAXException {
        Log.i("----->", "开始解析文档!");
        super.startDocument();
    }
    //开始解析文档元素
    @Override
    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
        Log.i("localName----->", localName);
        preTAG = localName;
        if ("student".equals(localName)) {
            stu = new Student();
            //将ID保存在stu中
            stu.setId(Long.parseLong(attributes.getValue(0)));
            for (int i = 0; i < attributes.getLength(); i++) {
                Log.i("attribute----->", String.valueOf(stu.getId()));
            }
        }
        //这句话记得要执行
        super.startElement(uri, localName, qName, attributes);
    }
    @Override
    public void endDocument() throws SAXException {
        Log.i("----->", "文档结束");
        super.endDocument();

    }
    @Override
    public void endElement(String uri, String localName, String qName) throws SAXException {
        preTAG = "";
        if ("student".equals(localName)) {
            ListStudent.add(stu);
            Log.i("----->", "一个元素解析完成!");
        }
        super.endElement(uri, localName, qName);
    }
    //解析节点文本内容
    @Override
    public void characters(char[] ch, int start, int length) throws SAXException {
        String str;
        //找出元素中的name节点
        if ("name".equals(preTAG)) {
            str = new String(ch,start,length);
            stu.setName(str);
            Log.i("name=", str);
        }else if("speciality".equals(preTAG)){
            str = new String(ch,start,length);
            stu.setSpeciality(str);
            Log.i("speciality=", str);
        }else if("qq".equals(preTAG)){
            str = new String(ch,start,length);
            stu.setQQ(Long.parseLong(str));
            Log.i("qq=", str);
        }

        super.characters(ch, start, length);
    }
    public void setListStudent(List<Student> listStudent) {
        ListStudent = listStudent;
    }
    public List<Student> getListStudent() {
        return ListStudent;
    }
}

这样我们就解析出xml的整个数据了,并在回调函数中将数据保存到了数组对象students中,我们查看一下打印出的log,分析一下SAX的解析过程。
这里写图片描述

我们可以看出这种按顺序解析XML文件标签的方式,完全符合回调函数中的说明。清晰明了。


Pull解析
pull解析和我们上面的SAX解析方法有些类似,Pull解析也提供了类似SAX的事件:

  1. START_DOCUMENT:开始文档;
  2. START_TAG:开始元素;
  3. TEXT:遇到元素内容;
  4. END_TAG:结束元素
  5. END_DOCUMENT:结束文档

Android系统提供了Pull解析的包org.xmlpull.v1,里面有PUll解析工厂类XMLPullParserFactory,和PULL解析器XmlParser。我们实例化工厂类,并获取xml解析器,接着XmlParser实例就可以调用getEventType()和next()等方法主动提取事件,并根据提取的事件做数据的处理。

PULL解析器有两种获取方法:

  1. 通过工厂类XMLPullParserFactory
  2. 通过Android实用工具类
protected List<Student> parserXML() {
        //初始化一个List<student>变量,用于存放student成员
        List<Student> studnets = null;
        //初始化student对象,用于存储每一个节点的信息
        Student stu = null;

        try {
            //打开资源文件
            InputStream inputStream = PullXMLActivity.this.getResources()
                    .getAssets().open("students.xml");
            //创建XmlParser有两种方法
            //方法一:使用工厂类XmlPullParserFactory
            XmlPullParserFactory pullFactory = XmlPullParserFactory.newInstance();
            XmlPullParser xmlPullParser = pullFactory.newPullParser();
            /* * //方法二:使用Android提供的实用工具类android.util.Xml //XmlPullParser xmlPullParser = Xml.newPullParser(); //设置输入字节流为UTF-8编码 * */
            xmlPullParser.setInput(inputStream, "utf-8");
            //取得事件类型,用于开始时的判断
            int eventType = xmlPullParser.getEventType();
            //循环遍历整个文件直到结束
            while(eventType != XmlPullParser.END_DOCUMENT){
                /* * 输出log显示事件类型 * START_DOCUMENT:0 * */
                Log.i("--->event", eventType+" ");
                //用于存储节点名称
                String localName = "";
                switch (eventType) {
                case XmlPullParser.START_DOCUMENT:
                    //碰到文档开头则实例化students变量,并输出log
                    studnets = new ArrayList<Student>();
                    Log.e("Pull---->", "start document");
                    break;
                case XmlPullParser.START_TAG:
                    localName = xmlPullParser.getName();
                    if ("student".equals(xmlPullParser.getName())) {
                        stu = new Student();
                        //将ID保存到stu中
                        stu.setId(Long.parseLong(xmlPullParser.getAttributeValue(0)));
                        Log.e("Pull----->", stu.getId()+"");
                    }else if(stu != null){
                        //声明一个变量用于存储节点文本
                        String currentData = null;
                        if ("name".equals(xmlPullParser.getName())) {
                            /* * 注意这里nextText()的使用:当前事件为START-TAG * 如果接下来是文本,就会返回当前的文本内容;如果下一个事件是End_TAG * 就会返回空字符串;否则抛出一个yichang */
                            currentData = xmlPullParser.nextText();
                            //存储name的信息
                            stu.setName(currentData);

                        }else if("speciality".equals(xmlPullParser.getName())){
                            currentData = xmlPullParser.nextText();
                            //存储专业信息
                            stu.setSpeciality(currentData);
                        }else if("qq".equals(xmlPullParser.getName())){
                            currentData = xmlPullParser.nextText();
                            //存储专业信息
                            stu.setQQ(Long.parseLong(currentData));
                        }
                    }
                    break;
                case XmlPullParser.END_TAG:
                    localName = xmlPullParser.getName();
                    Log.e("Pull----->", localName);
                    if ("student".equals(localName) && stu != null) {
                        studnets.add(stu);
                        stu = null;
                    }
                    break;
                default:
                    break;
                }
                //解析下一事件
                eventType = xmlPullParser.next();
            }
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return studnets;
    }

这里也打印出log贴出来并做出了分析
这里写图片描述

总结:
SAX和PULL解析器虽然在代码上可能写的有些复杂,但是它们的解析效率,和思维逻辑的清晰都是非常好的,值得我们在软件开发中使用。

本文转载自:http://blog.csdn.net/yin569258/article/details/50903051

共有 人打赏支持
YH_猿员猿
粉丝 0
博文 12
码字总数 0
作品 0
徐汇
程序员
Android中Layout转成Java代码

android中总是要给控件指定一个id,然后还要在代码中写一个控件名称,两者要对应起来,这个工作本身就是体力劳动。这里我自己写了一个小的代码生成工具类,将anroid的xml布局文件生成为java文...

苏谷子
2014/12/23
2.8K
0
ARCore:OpenGL ES环境搭建

估计大部分Anroid开发的同学,对OpenGL ES的了解可能也仅仅停留在三维图形的渲染,入门模板代码的编写阶段。在ARCore开发中,如果你选择使用Android+OpenGL ES的开发技术栈,就需要大家深入的...

p106786860
2017/12/04
0
0
Xamarin Anroid App访问网站失败

Xamarin Anroid App访问网站失败 错误信息:net::ERRNAMENOT_RESOLVED 如果电脑同时有有线网卡和无线网卡,电脑使用无线网卡上网,而有线网卡不上网。这时,就会出现这个问题。这是因为Andro...

大学霸
2016/07/14
7
0
Android Studio 调试会出现安装两个相同的APP?!

新手学习中 网上载了个项目Eclipse运行没问题。anroid studio运行各种问题 友盟在AndroidManifest.xml的key配置加上就出错 注释之后运行安装两个一样的APP进去,删除一个则全部删除。Eclipse...

李剑
2015/07/22
3.9K
1
contentprovider学习笔记

学习Contentprovider Uri的格式:“content://”+authority+“/表名” 字符串转成Uri格式:Uri.parse( ); 获取Cursor某一项的数据: Cursor 先锁定某一行:如cursor.movetofirst( ); Cursor...

ctozhong
2014/05/11
0
0
Xamarin Anroid开发教程之Anroid开发工具及应用介绍

Xamarin Anroid开发教程之Anroid开发工具及应用介绍 Xamarin开发Anroid应用介绍 如今智能手机已经盛行了好几年,而针对这些智能手机的软件开发也变得异常火热。但是在Android平台下只能使用J...

大学霸
2015/05/13
0
0
springmvc+mybatis +Jeesz 分布式架构

spring mvc Spring框架(框架即:编程注解+xml配置的方式)MVC是Spring框架的一大特征,Spring框架有三大特征(IOC(依赖注入),AOP(面向切面),MVC(建模M-视图V-控制器C)。框架一般用于...

愉快的鱼儿
2017/06/01
0
0
springmvc+mybatis +Jeesz 分布式架构

spring mvc Spring框架(框架即:编程注解+xml配置的方式)MVC是Spring框架的一大特征,Spring框架有三大特征(IOC(依赖注入),AOP(面向切面),MVC(建模M-视图V-控制器C)。框架一般用于...

愉快的鱼儿
2017/05/16
0
0
Facebook 发布 React Native for Android

Facebook 今天发布了 React Nativefor Android,把 Web 和原生平台的 JavaScript 开发技术扩展到了 Google 的流行移动平台。 React Native 让开发者使用 JavaScript 和 React 编写应用,利用...

oschina
2015/09/15
16.7K
64
常见C/C++ XML解析器比较

常见C/C++ XML解析器有tinyxml、XERCES、squashxml、xmlite、pugxml、libxml等等,这些解析器有些是支持多语言的,有些只是单纯C/C++的。如果你是第一次接触到XML解析,那么关于XML解析器的选...

moki_oschina
2015/12/09
74
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Java架构师知识体认识

源码分析 常用设计模式 Proxy代理模式 Factory工厂模式 Singleton单例模式 Delegate委派模式 Strategy策略模式 Prototype原型模式 Template模板模式 Spring5 beans 接口实例化 代理Bean操作 ...

小致dad
15分钟前
0
0
SpringBoot | 第十章:Swagger2的集成和使用

前言 前一章节介绍了mybatisPlus的集成和简单使用,本章节开始接着上一章节的用户表,进行Swagger2的集成。现在都奉行前后端分离开发和微服务大行其道,分微服务及前后端分离后,前后端开发的...

oKong
今天
9
0
Python 最小二乘法 拟合 二次曲线

Python 二次拟合 随机生成数据,并且加上噪声干扰 构造需要拟合的函数形式,使用最小二乘法进行拟合 输出拟合后的参数 将拟合后的函数与原始数据绘图后进行对比 import numpy as npimport...

阿豪boy
今天
12
0
云拿 无人便利店

附近(上海市-航南路)开了家无人便利店.特意进去体验了一下.下面把自己看到的跟大家分享下. 经得现场工作人员同意后拍了几张照片.从外面看是这样.店门口的指导里强调:不要一次扫码多个人进入....

周翔
昨天
1
0
Java设计模式学习之工厂模式

在Java(或者叫做面向对象语言)的世界中,工厂模式被广泛应用于项目中,也许你并没有听说过,不过也许你已经在使用了。 简单来说,工厂模式的出现源于增加程序序的可扩展性,降低耦合度。之...

路小磊
昨天
203
1
npm profile 新功能介绍

转载地址 npm profile 新功能介绍 npm新版本新推来一个功能,npm profile,这个可以更改自己简介信息的命令,以后可以不用去登录网站来修改自己的简介了 具体的这个功能的支持大概是在6这个版...

durban
昨天
1
0
Serial2Ethernet Bi-redirection

Serial Tool Serial Tool is a utility for developing serial communications, custom protocols or device testing. You can set up bytes to send accordingly to your protocol and save......

zungyiu
昨天
1
0
python里求解物理学上的双弹簧质能系统

物理的模型如下: 在这个系统里有两个物体,它们的质量分别是m1和m2,被两个弹簧连接在一起,伸缩系统为k1和k2,左端固定。假定没有外力时,两个弹簧的长度为L1和L2。 由于两物体有重力,那么...

wangxuwei
昨天
0
0
apolloxlua 介绍

##项目介绍 apolloxlua 目前支持javascript到lua的翻译。可以在openresty和luajit里使用。这个工具分为两种模式, 一种是web模式,可以通过网页使用。另外一种是tool模式, 通常作为大规模翻...

钟元OSS
昨天
2
0
Mybatis入门

简介: 定义:Mybatis是一个支持普通SQL查询、存储过程和高级映射的持久层框架。 途径:MyBatis通过XML文件或者注解的形式配置映射,实现数据库查询。 特性:动态SQL语句。 文件结构:Mybat...

霍淇滨
昨天
2
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部