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.基本读取(查)
代码如下
SAXParserFactoryfactory=SAXParserFactory.newInstance();//创建SAX解析工厂 SAXParsersaxParser; try{ Filefile=newFile(xmlFilePath); InputStreaminputStream=newFileInputStream(file);//得到输入流 saxParser=factory.newSAXParser();//创建解析器 saxParser.parse(inputStream,newDefaultHandler(){//开始解析 //文档开始标记 @Override publicvoidstartDocument()throwsSAXException{ super.startDocument(); Log.i("loadWithSax","startDocument"); } //文档结束标记 @Override publicvoidendDocument()throwsSAXException{ super.endDocument(); FileUtils.closeIO(inputStream); Log.i("loadWithSax","endDocument"); } //解析到标签 @Override publicvoidstartElement(Stringuri,StringlocalName,StringqName,Attributesattributes)throwsSA super.startElement(uri,localName,qName,attributes); Log.i("loadWithSax","startElement"+",uri:"+uri+",localName:"+localName+",qName:"+qName); if(attributes!=null){ for(inti=0;i"的位置。length就是">"到下一个"<"的长度。 * * *执行namesList节点时,因为没有文本, *不会执行到该方法。 */ @Override publicvoidcharacters(char[]ch,intstart,intlength)throwsSAXException{ super.characters(ch,start,length); Log.i("loadWithSax","characters"+",start:"+start+",length:"+length); for(inti=0;imichael *
- 传入:DefaultHandler的实体,通过复写其中的方法,查询到文档,标签的内容:
- startDocument和endDocument是扫描文档的开始和结束
- startElement,是解析到了标签,localName就是标签的名称,如本文所示例的,当解析到第一个人名的时候,
zhangsan 21 解析到
回调:startElement,标签内的参数是Attributesattributes,一个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:namestartDocument,开始解析xml
解析到第一个标签的开始:
然后解析到了内容???characters?按照我上面的分析,
标签内没有文字内容,应该不会回调。其实,这里回调的是换行符。log中打出了ASCII码,10就是换行。然后,还有一个tab符。
然后就是
里面的 ,有三个参数:id,key,type,巴拉巴拉。。。
3.保存
sax的保存有点麻烦。具体是XmlSerializer的使用。
初始化一个XmlSerializer:
StringWriterstringWriter=newStringWriter(); XmlPullParserFactoryfactory=XmlPullParserFactory.newInstance(); XmlSerializerxmlSerializer=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:
publicclassPerson{ publicintid=-1; publicStringkey=null; publicStringtype=null; publicStringname; publicintage; publicPerson(Stringname,intage){ this.name=name; this.age=age; } }然后开撸:最后的stringWriter就是你想要的数据,注意就是,一些换行和tab符。
StringWriterstringWriter=newStringWriter(); try{ XmlPullParserFactoryfactory=XmlPullParserFactory.newInstance(); XmlSerializerxmlSerializer=factory.newSerializer(); xmlSerializer.setOutput(stringWriter); //制造假数据: ArrayListpersonArrayList=newArrayList<>(); Personperson1=newPerson("zhangsan",21); person1.id=1; person1.key="33"; person1.type="type"; Personperson2=newPerson("lisi",12); Personperson3=newPerson("wangwu",23); personArrayList.add(person1); personArrayList.add(person2); personArrayList.add(person3); //stardocument xmlSerializer.startDocument("utf-8",true); xmlSerializer.text("\n"); xmlSerializer.startTag(null,"persons"); for(Personperson:personArrayList){ //startag 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"); //endtag xmlSerializer.text("\n"); xmlSerializer.text("\t"); xmlSerializer.endTag(null,"person"); } //enddocument xmlSerializer.text("\n"); xmlSerializer.endTag(null,"persons"); xmlSerializer.endDocument(); }catch(Exceptione){ e.printStackTrace(); } XmlSerializer的初始化需要传入一个write对象,你可以传入一个FileWrite,写到文件里面:
//创建文件对象 FilefileText=newFile(saveFilePath); //向文件写入对象写入信息 FileWriterstringWriter; xmlSerializer.setOutput(stringWriter); //...同上 //记得close if(stringWriter!=null){ stringWriter.close(); }4.增删
增加和删除,那么你需要先对XML进行映射,映射成一堆的Bean,然后增加删除Bean,再保存即可。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。