Android利用SAX对XML进行增删改查操作详解

前言

解析XML的方式有很多种,大家比较熟悉的可能就是DOM解析。

DOM(文件对象模型)解析:解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以根据DOM接口来操作这个树结构了。

  优点:整个文档读入内存,方便操作:支持修改、删除和重现排列等多种功能。

  缺点:将整个文档读入内存中,保留了过多的不需要的节点,浪费内存和空间。

  使用场合:一旦读入文档,还需要多次对文档进行操作,并且在硬件资源充足的情况下(内存,CPU)。

为了解决DOM解析存在的问题,就出现了SAX解析。其特点为:

  优点:不用实现调入整个文档,占用资源少。尤其在嵌入式环境中,如android,极力推荐使用SAX解析。

  缺点:不像DOM解析一样将文档长期驻留在内存中,数据不是持久的。如果事件过后没有保存数据,数据就会丢失。

  使用场合:机器有性能限制。

本文将给大家详细介绍关于Android利用SAX对XML增删改查的相关内容,分享出来供大家参考学习价值,下面话不多说了,来一起看看详细的介绍吧。

1.概述

SAX是一中事件驱动类型的XML解析方式。说白了,就是通过复写一个Default类去告知,解析的结果。SAX并不会想DOM那样把整个的XML加载到内存中,而它会像IO流那样,一个一个标签地去解析。

简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。

为了方便说明,先约定好一个XML如下:

<?xml version="1.0" encoding="UTF-8"?>
<persons>
 <person id="1" key="33" type="type">
  <name>zhangsan</name>
  <age>21</age>
 </person>
</persons>

2.基本读取(查)

代码如下

SAXParserFactory factory = SAXParserFactory.newInstance();//创建SAX解析工厂
SAXParser saxParser;
try {
 File file = new File(xmlFilePath);
 InputStream inputStream = new FileInputStream(file);//得到输入流
 saxParser = factory.newSAXParser();//创建解析器
 saxParser.parse(inputStream,new DefaultHandler(){//开始解析
  //文档开始标记
  @Override
  public void startDocument() throws SAXException {
   super.startDocument();
   Log.i("loadWithSax","startDocument");
  }
  //文档结束标记
  @Override
  public void endDocument() throws SAXException {
   super.endDocument();
   FileUtils.closeIO(inputStream);
   Log.i("loadWithSax","endDocument");
  }
  //解析到标签
  @Override
  public void startElement(String uri, String localName, String qName, Attributes attributes) throws SA
   super.startElement(uri, localName, qName, attributes);
   Log.i("loadWithSax","startElement"+",uri:"+uri+",localName:"+localName+",qName:"+qName);
   if (attributes!=null) {
    for (int i = 0; i < attributes.getLength(); i++) {
     Log.i("loadWithSax",attributes.getLocalName(i)+","+attributes.getValue(i)+","+attributes.
    }
   }
  }
  //标签解析结束
  @Override
  public void endElement(String uri, String localName, String qName) throws SAXException {
   super.endElement(uri, localName, qName);
   Log.i("loadWithSax","endElement"+",uri:"+uri+",localName:"+localName+",qName:"+qName);
  }
  /**
   * 文本
   * 该方法中的ch把所解析的xml的所有数据都保存进来,且ch初始化为2K数据。 start是一个节点">"的位置。length就是">"到下一个"<"的长度。
   * <namesList>
   *  <name>michael</name>
   * </namesList>
   * 执行namesList节点时,因为没有文本,
   * 不会执行到该方法。
   */
  @Override
  public void characters(char[] ch, int start, int length) throws SAXException {
   super.characters(ch, start, length);
   Log.i("loadWithSax","characters"+",start:"+start+",length:"+length);
   for (int i = 0; i < ch.length; i++) {
    Log.i("loadWithSax","char:"+ch[i]+",ASCII:"+(int)ch[i]);
   }
  }
  //警告回调
  @Override
  public void warning(SAXParseException e) throws SAXException {
   super.warning(e);
   Log.i("loadWithSax","warning"+","+e.getMessage());
  }
  //错误回调
  @Override
  public void error(SAXParseException e) throws SAXException {
   super.error(e);
   Log.i("loadWithSax","error1"+","+e.getMessage());
  }
 });
} catch (ParserConfigurationException | SAXException | IOException e) {
 e.printStackTrace();
 Log.i("loadWithSax","error2"+","+e.getMessage());
}
  • 传入:DefaultHandler的实体,通过复写其中的方法,查询到文档,标签的内容:
  • startDocument 和 endDocument是扫描文档的开始和结束
  • startElement,是解析到了标签,localName就是标签的名称,如本文所示例的,当解析到第一个人名的时候,
<person id="1" key="33" type="type">
 <name>zhangsan</name>
 <age>21</age>
</person>

解析到<person></person>回调:startElement,标签内的参数是Attributes attributes,一个for循环就可以遍历读取。

characters,解析到标签的内容时候回调,接着上面例子,解析<person></person>,回调startElement,然后不会回调此方法,因为内容不是文本,而是包含了标签,所以,解析到其子标签:<name>zhangsan</name>的时候,又会先回调回调startElement,然后,才回调characters,告诉你,这个标签里面有文本内容!参数说明如下:

  • char[] : 内容字符数组里面。如:<name>zhangsan</name>,char[]就是:{'z','h','a','n','g','s','a','n'}
  • start :0,文本的开始
  • length :文本的长度。
  • endElement,标签结束。

使用上面的代码,得到的部分log如下:

I/loadWithSax: startDocument
I/loadWithSax: startElement,uri:,localName:persons,qName:persons
I/loadWithSax: characters,start:0,length:1
I/loadWithSax: char:
    ,ASCII:10
I/loadWithSax: characters,start:0,length:1
I/loadWithSax: char: ,ASCII:9
I/loadWithSax: startElement,uri:,localName:person,qName:person
I/loadWithSax: id,1,CDATA
I/loadWithSax: key,33,CDATA
I/loadWithSax: type,type,CDATA
I/loadWithSax: characters,start:0,length:1
I/loadWithSax: char:
    ,ASCII:10
I/loadWithSax: characters,start:0,length:2
I/loadWithSax: char: ,ASCII:9
I/loadWithSax: char: ,ASCII:9
I/loadWithSax: startElement,uri:,localName:name,qName:name
I/loadWithSax: characters,start:0,length:8
I/loadWithSax: char:z,ASCII:122
I/loadWithSax: char:h,ASCII:104
I/loadWithSax: char:a,ASCII:97
I/loadWithSax: char:n,ASCII:110
I/loadWithSax: char:g,ASCII:103
I/loadWithSax: char:s,ASCII:115
I/loadWithSax: char:a,ASCII:97
I/loadWithSax: char:n,ASCII:110
I/loadWithSax: endElement,uri:,localName:name,qName:name

startDocument,开始解析xml

解析到第一个标签的开始:<persons>

然后解析到了内容???characters?按照我上面的分析,<persons>标签内没有文字内容,应该不会回调。其实,这里回调的是换行符。log中打出了ASCII码,10就是换行。然后,还有一个tab符。

然后就是<persons>里面的<person>,有三个参数:id,key,type,巴拉巴拉。。。

3.保存

sax的保存有点麻烦。具体是XmlSerializer的使用。

初始化一个XmlSerializer:

StringWriter stringWriter = new StringWriter();
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
XmlSerializer xmlSerializer = factory.newSerializer();
xmlSerializer.setOutput(stringWriter);

声明文档的开始和结束:

xmlSerializer.startDocument("utf-8", false);//false,是声明:standalone的值。
xmlSerializer.endDocument();

标签的开始结束,和写入内容:

xmlSerializer.startTag(null, "name");//开始,第一个参数是namespace,命名空间。
xmlSerializer.text(person.name);//写入内容
xmlSerializer.endTag(null, "name");

实战:

假如,我们需要构建如下的XML:

<?xml version='1.0' encoding='utf-8' standalone='yes' ?>
<persons>
 <person id="1" key="33" type="type">
  <name>zhangsan</name>
  <age>21</age>
 </person>
 <person>
  <name>lisi</name>
  <age>12</age>
 </person>
 <person>
  <name>wangwu</name>
  <age>23</age>
 </person>
</persons>

首先你得定义好一个Bean类,Person:

public class Person {
 public int id = -1;
 public String key = null;
 public String type = null;
 public String name;
 public int age;
 public Person(String name, int age) {
  this.name = name;
  this.age = age;
 }
}

然后开撸:最后的stringWriter就是你想要的数据,注意就是,一些换行和tab符。

StringWriter stringWriter = new StringWriter();
try {
  XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
  XmlSerializer xmlSerializer = factory.newSerializer();
  xmlSerializer.setOutput(stringWriter);
  //制造假数据:
  ArrayList<Person> personArrayList = new ArrayList<>();
  Person person1 = new Person("zhangsan",21);
  person1.id=1;
  person1.key="33";
  person1.type="type";
  Person person2 = new Person("lisi",12);
  Person person3 = new Person("wangwu",23);
  personArrayList.add(person1);
  personArrayList.add(person2);
  personArrayList.add(person3);
  //star document
  xmlSerializer.startDocument("utf-8", true);
  xmlSerializer.text("\n");
  xmlSerializer.startTag(null, "persons");
  for(Person person:personArrayList){
    //star tag
    xmlSerializer.text("\n");
    xmlSerializer.text("\t");
    xmlSerializer.startTag(null, "person");
    //添加参数
    if (person.id!=-1) {
      xmlSerializer.attribute(null,"id",String.valueOf(person.id));
    }
    if (person.key!=null) {
      xmlSerializer.attribute(null,"key",person.key);
    }
    if (person.type!=null) {
      xmlSerializer.attribute(null,"type",person.type);
    }
    //添加内容:name
    xmlSerializer.text("\n");
    xmlSerializer.text("\t");
    xmlSerializer.text("\t");
    xmlSerializer.startTag(null, "name");
    xmlSerializer.text(person.name);
    xmlSerializer.endTag(null, "name");
    //添加内容:age
    xmlSerializer.text("\n");
    xmlSerializer.text("\t");
    xmlSerializer.text("\t");
    xmlSerializer.startTag(null, "age");
    xmlSerializer.text(String.valueOf(person.age));
    xmlSerializer.endTag(null, "age");
    //end tag
    xmlSerializer.text("\n");
    xmlSerializer.text("\t");
    xmlSerializer.endTag(null, "person");
  }
  //end document
  xmlSerializer.text("\n");
  xmlSerializer.endTag(null, "persons");
  xmlSerializer.endDocument();
} catch (Exception e) {
  e.printStackTrace();
}

XmlSerializer的初始化需要传入一个write对象,你可以传入一个FileWrite,写到文件里面:

// 创建文件对象
File fileText = new File(saveFilePath);
// 向文件写入对象写入信息
FileWriter stringWriter;
xmlSerializer.setOutput(stringWriter);
//...同上
//记得close
if (stringWriter != null) {
  stringWriter.close();
}

4.增删

增加和删除,那么你需要先对XML进行映射,映射成一堆的Bean,然后增加删除Bean,再保存即可。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对我们的支持。

(0)

相关推荐

  • 详解Android之解析XML文件三种方式(DOM,PULL,SAX)

    1.xml文件代码 <?xml version="1.0" encoding="UTF-8" ?> <%@ page language="java" contentType="text/xml; charset=UTF-8" pageEncoding="UTF-8"%> <%@ taglib uri="http://java.sun.com/jsp/jstl/core

  • Android开发之DOM解析xml文件的方法

    本文实例讲述了Android中DOM解析xml文件的方法.分享给大家供大家参考,具体如下: 一.在assets文件中写xml文件 <?xml version="1.0" encoding="UTF-8"?> <persons> <person id="23"> <name>李明</name> <age>30</age> </person> <pe

  • Android 创建与解析XML(五)——详解Dom4j方式

    1.Dom4j概述 dom4j is an easy to use, open source library for working with XML, XPath and XSLT on the Java platform using the Java Collections Framework and with full support for DOM, SAX and JAXP. dom4j官方网址:dom4j dom4j源码下载:dom4j download 本示例中,需要导入dom4j

  • Android创建与解析XML(二)——详解Dom方式

    1. Dom概述 Dom方式创建XML,应用了标准xml构造器 javax.xml.parsers.DocumentBuilder 来创建 XML 文档,需要导入以下内容 javax.xml.parsers javax.xml.parsers.DocumentBuilder javax.xml.parsers.DocumentBuilderFactory javax.xml.parsers.ParserConfigurationException; javax.xml.transform jav

  • Android应用中使用DOM方式解析XML格式数据的基本方法

    DOM比SAX更容易掌握,因为她没有涉及回调和复杂的状态管理,然而,DOM的实现常常将所有的XML节点保存在内存中,这样使的处理较大的文档效率低. XML基本的节点类型 node - DOM基本的数据类型 Element - 最主要处理的对象是Element Attr - 元素的属性 Text - 一个Element 或者Attr的实际内容 Document - 代表整个XML文档,一个Document对象通常也称为一颗DOM树   1.在src目录下新建一个android.xml <?xml

  • Android编程解析XML方法详解(SAX,DOM与PULL)

    本文实例讲述了Android编程解析XML方法.分享给大家供大家参考,具体如下: XML在各种开发中都广泛应用,Android也不例外.作为承载数据的一个重要角色,如何读写XML成为Android开发中一项重要的技能.今天就由我向大家介绍一下在Android平台下几种常见的XML解析和创建的方法. 在Android中,常见的XML解析器分别为SAX解析器.DOM解析器和PULL解析器,下面,我将一一向大家详细介绍. SAX解析器: SAX(Simple API for XML)解析器是一种基于事

  • Android利用Dom对XML进行增删改查操作详解

    1. 概述 平常我们一般是使用JSON与服务器做数据通信,JSON的话,直接用GSON或者其他库去解析很简单.但是,其他有些服务器会返回XML格式的文件,这时候就需要去读取XML文件了. XML的解析有三种方式,在Android中提供了三种解析XML的方式:DOM(Document Objrect Model) , SAX(Simple API XML) ,以及Android推荐的Pull解析方式,他们也各有弊端,而这里来看看使用DOM的方式. 2. Dom解析 DOM解析器在解析XML文档时,

  • Android解析XML的三种方式SAX、Pull、Dom

    在android开发中,经常用到去解析xml文件,常见的解析xml的方式有一下三种:SAX.Pull.Dom解析方式.最近做了一个android版的CSDN阅读器,用到了其中的两种(sax,pull),本文对android解析xml的这三种方式进行一次总结. 今天解析的xml示例(channels.xml)如下: <?xml version="1.0" encoding="utf-8"?> <channel> <item id=&quo

  • Android利用SAX对XML进行增删改查操作详解

    前言 解析XML的方式有很多种,大家比较熟悉的可能就是DOM解析. DOM(文件对象模型)解析:解析器读入整个文档,然后构建一个驻留内存的树结构,然后代码就可以根据DOM接口来操作这个树结构了. 优点:整个文档读入内存,方便操作:支持修改.删除和重现排列等多种功能. 缺点:将整个文档读入内存中,保留了过多的不需要的节点,浪费内存和空间. 使用场合:一旦读入文档,还需要多次对文档进行操作,并且在硬件资源充足的情况下(内存,CPU). 为了解决DOM解析存在的问题,就出现了SAX解析.其特点为: 优

  • java中JDBC增删改查操作详解

    目录 前言 一.增删改操作 1.1 PreparedStatement介绍  1.2 增删改操作   1.3 测试 二.查操作 2.1 通用对不同表进行一条数据查询操作 2.2 通用对不同表进行多条数据查询操作 总结 前言         在上一篇博客我们介绍了JDBC的概念以及连接数据库的五种方式JDBC概述及数据库连接方式(数据库连接方式推荐使用第五种),那么我们既然连接上数据库了,那就要对数据进行操作了,那么这一篇我们就来介绍常规的增删改 查操作.       我们先看一遍步骤:    

  • MySQL筑基篇之增删改查操作详解

    目录 一.增加表中数据 1.无自增列时 2.有自增列时 二.删除表中数据 1.使用delete 2.使用truncate 三.修改表中数据 四.*查询操作 1.简单查询 2.条件查询 3.排序 一.增加表中数据 1.无自增列时 1.指定字段添加数据 给表中的部分列添加数据:值的顺序必须跟指定列的顺序保持一致 语法:insert into 表名(列1,列2,...) values(值1,值2,...) 2.默认添加数据 向表中的所有列添加数据:值的顺序必须跟字段顺序保持一致 语法:insert i

  • Python实现连接MySql数据库及增删改查操作详解

    本文实例讲述了Python实现连接MySql数据库及增删改查操作.分享给大家供大家参考,具体如下: 在本文中介绍 Python3 使用PyMySQL连接数据库,并实现简单的增删改查.(注意是python3) 1.安装PyMySQL PyMySQL 是在 Python3.x 版本中用于连接 MySQL 服务器的一个库,Python2中则使用mysqldb.PyMySQL 遵循 Python 数据库 API v2.0 规范,并包含了 pure-Python MySQL 客户端库.在使用 PyMySQ

  • python3.6连接mysql数据库及增删改查操作详解

    折腾好半天的数据库连接,由于之前未安装 pip ,而且自己用的python 版本为3.6. 只能用 pymysql 来连接数据库,下边 简单介绍一下 连接的过程,以及简单的增删改查操作. 1.通过 pip 安装 pymysql 进入 cmd  输入  pip install pymysql   回车等待安装完成: 安装完成后出现如图相关信息,表示安装成功. 2.测试连接 import pymysql #导入 pymysql 如果编译未出错,即表示 pymysql 安装成功 简单的增删改查操作 示

  • express+mongoose实现对mongodb增删改查操作详解

    本文实例讲述了express+mongoose实现对mongodb增删改查操作.分享给大家供大家参考,具体如下: 项目地址:https://github.com/jrainlau/mongoose_crud 写在开头 本文主要分享我如何使用express+mongoose对mongodb实现增删改查操作,感谢cnode社区所有精品文章的帮助,以及@airuikun的开源项目airuikun/mongoose_crud对我的启发. 学习nodejs已经小半个月了,一直琢磨着做一些什么东西出来.由于

  • AJAX实现数据的增删改查操作详解【java后台】

    本文实例讲述了AJAX实现数据的增删改查操作.分享给大家供大家参考,具体如下: 主页:index.html <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <script src="http://libs.baidu.com/jquery/2.1.4/jquery.min.js"></sc

  • PHP实现对xml的增删改查操作案例分析

    本文实例讲述了PHP实现对xml的增删改查操作.分享给大家供大家参考,具体如下: 案例: index.php <?php header("content-type:text/html;charset=utf-8"); $xmldom = new DOMDocument(); $xmldom->load("demo2.xml"); //查询学生信息 $stus = $xmldom->getElementsByTagName("学生"

  • Java对XML文件增删改查操作示例

    本文实例讲述了Java对XML文件增删改查操作.分享给大家供大家参考,具体如下: xml文件: <?xml version="1.0" encoding="UTF-8"?> <books> <book> <name>哈里波特</name> <price>10</price> <memo>这是一本很好看的书.</memo> </book> <b

随机推荐