android 增删改查错误,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如下:

zhangsan

21

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就是">"到下一个"

*

* michael

*

* 执行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就是标签的名称,如本文所示例的,当解析到第一个人名的时候,

zhangsan

21

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

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

char[] : 内容字符数组里面。如:zhangsan,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

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

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

然后就是里面的,有三个参数: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:

zhangsan

21

lisi

12

wangwu

23

首先你得定义好一个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 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
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值