Java sax、dom、pull解析xml
-------------------------------------SAX解析xml----------------------------------
》Sax定义
SAX是一个解析速度快并且占用内存少的xml解析器,非常适合用于android等移动设备
SAX全称是Simple API for Xml,既是指一种接口,也是一个软件包
作为接口,sax是事件驱动型xml解析的一个标准接口
》Sax特点
1. 解析效率高,占用内存少
2.可以随时停止解析
3.不能载入整个文档到内存
4.不能写入xml
5.SAX解析xml文件采用的是事件驱动
---sax并不需要解析完 整个文档,在按内容顺序解析文档的过程中,sax会判断当前读到的字符是否合法xml语法中的某部分,如果符合就会触发事件
》Sax工作原理
Sax的工作原理简单的说,就是对文档进行顺序扫描,扫描到文档(document)开始与结束,扫描到元素(element)开始、结束等地方时调用事件处理
处理函数做相应动作,然后继续扫描,直到文档结束。
》Sax解析文档过程
1.继承DefaultHandler ,并实现方法
2.创建SAX解析器工厂
3.获得解析器
4.获得输入流
5.使用输入流,和实现接口作参数,调用解析器的解析方法进行解析
》defaultHandler 接口是实现contentHandler接口
ContentHandler接口中的常用方法
>startDocument()
当遇到文档开头的时候,调用这个方法,可以在其中做一些与准备工作
>endDocument()
当文档结束的时候,调用这个方法,可以在其中做一些善后工作
>startElement(String namespaceURL, String localName, String qName, Attributes atts)
当读到一个开始标签的时候,会触发这个方法。namespaceURL就是命名空间,localName是不带命名空间前缀的标签名,
qName是待命名空间前缀的标签名。通过atts可以得到所有的属性名和相应的值。
>endElement(String uri, String localName, String name)
当遇到结束标签的时候,调用这个方法
>characters(char[] ch, int start, int length)
这个方法用来处理在xml文件中读到的内容,第一个参数为文件的字符串内容,后面两个参数是读到的字符串在这个数组中的起始位置和长度,
使用new String(ch, start, length)就可以获取内容
》SAX解析实例
-------------1.在src下创建xml 文件,并结合成实体类Userinfo.java-------------
<?xml version="1.0" encoding="UTF-8"?>
<admins>
<admin id="1">
<name>阿龙</name>
<age>23</age>
<sex>男</sex>
<email>along@qq.com</email>
</admin>
</admins>
----------Userinfo.java----
String name;
int age;
String sex;
String email;
String id;
。。。 生成get、set方法
--------------------2.创建XmlPaser继承defaultHandler----------------------
public class XmlPaser extends DefaultHandler{
//创建user对象为把查到的内容放到里面
Userinfo user;
public Userinfo getUser() {
return user;
}
public void setUser(Userinfo user) {
this.user = user;
}
//定义标签变量
String tagName = null;
//开始文档处理些准备工作
public void startDocument() throws SAXException {
user = new Userinfo();
super.startDocument();
}
//读到第一个标签触发
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
tagName = localName;
if("admin".equals(tagName)){
user.setId(attributes.getValue(0));
System.out.println("id: "+attributes.getValue(0));
}
}
//读取文本内容
public void characters(char[] ch, int start, int length)
throws SAXException {
if(tagName!=null){
if("name".equals(tagName)){
String str = new String(ch,start,length);
user.setName(str);
System.out.println("name: "+str);
}else if("age".equals(tagName)){
String str = new String(ch,start,length);
user.setAge(Integer.parseInt(str));
System.out.println("age: "+str);
}else if("sex".equals(tagName)){
String str = new String(ch,start,length);
user.setSex(str);
System.out.println("sex: "+str);
}else if("email".equals(tagName)){
String str = new String(ch,start,length);
user.setEmail(str);
System.out.println("email: "+str);
}
}
}
//遇到结束标签
public void endElement(String uri, String localName, String qName)
throws SAXException {
tagName=null;
}
//文档读完
public void endDocument() throws SAXException {
super.endDocument();
}
}
----------------布局文件main省略-----------
----------------------3.-类SAXActivity继承Activity----------------
Button btnOk;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
btnOk = (Button)this.findViewById(R.id.button1);
btnOk.setOnClickListener(new OnClickListener() {
public void onClick(View v){
//创建解析工厂和解析器
SAXParserFactory spf = SAXParserFactory.newInstance();
try{
SAXParser sp = spf.newSAXParser();
//解析
XmlPaser xp = new XmlPaser();
InputStream is = this.getClass().getClassLoader().getResourceAsStream("user.xml");
sp.parse(is,xp);
//获得读取到的内容
Userinfo user = xp.getUser();
//在页面显示
.................
}
}
});
}
---------------------------------------Dom解析Xml--------------------------------------------
》DOM简介
dom全称Document Object Model ,为xml文档的已解析版本定义了一组接口。解析器读入整个文档,然后构建一个主流内存的树结构,
然后代码就可以使用dom接口来操作这个树结构
》DOM的特点
>优点
1.整个文档树在内存中,便于操作;支持删除、修改、重新排列等多种功能
2.通过树形结构存取xml文档
3.可以在树的某个节点上向前或向后移动
>缺点
1.将整个文档调入内存(包括无用的节点),浪费时间和空间
>适用场合
一旦解析了文档还需多次访问这些数据;硬件资源充足(内存,cpu)
》DOM解析步骤
1.创建解析器工厂
2.获得解析器工厂
3.接受一个xml文档作为输入参数名,并得到一个xml的文档对象(Document)
4.操作文档对象
》解析实例:
-----------------------1.创建要解析的xml文件、和实体类(Person)---------------------------
<?xml version="1.0" encoding="utf-8"?>
<users>
<user id="1">
<name>Tom</name>
<age>19</age>
</user>
<user id="2">
<name>Jaary</name>
<age>18</age>
</user>
</users>
实体类 略
-----------------------2. Dom解析(DomService.java)-----------------------------------
public List<Person> getPersons(InputStream input) throws Throwable{
//获得解析器工厂
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
//获得解析器
DocumentBuilder builder = factory.newDocumentBuilder();
//进行解析
Document doc = builder.parse(input);
List<Person> personlist = new new ArrayList<Person>();
//获得所有叫user的节点
NodeList list = doc.getElementsByTagName(user);
String id="";
String name="";
String age="";
for(int i=0;i<list.getLength();i++){
//取得第i个user节点
Element node=(Element)list.item(i);
Person p=new Person();
//获取id属性
id=node.getAttribute("id");
//获得user节点下的子节点列表
NodeList userList=node.getChildNodes();
for(int j=0;j<userList.getLength();j++){
//判断是否是元素节点,name和age属于元素节点
if(userList.item(j).getNodeType()==Node.ELEMENT_NODE){
Element childNode=(Element)userList.item(j);
if("name".equals(childNode.getNodeName())){
name=childNode.getFirstChild().getNodeValue();
}
else if("age".equals(childNode.getNodeName())){
age=childNode.getFirstChild().getNodeValue();
}
p.setName(name);
p.setAge(age);
p.setId(Integer.parseInt(id));
}
}
personList.add(p);
}
return personList;
}
-------------------------3.Activity01继承Activity类----------------------------------------------------
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
InputStream is=this.getClass().getClassLoader().getResourceAsStream("test.xml");
DomService dom=new DomService();
try {
List<Person> ps=dom.getPersons(is);
for(Person p:ps){
System.out.println(p.getId());
System.out.println(p.getName());
System.out.println(p.getAge());
}
} catch (Exception e) {
e.printStackTrace();
}
}
--------------------------------------pull解析-----------------------------
》pull解析器简介
1.pull解析器是android内置的解析器,解析原理与sax类似
2.pull它提供了类似的事件。
如:开始元素和结束元素事件,使用parse.next()可以进入下一个元素并触发相应的事件,事件将作为数值代码被发送
因此可以使用一个switch对感兴趣的事件进行处理。当元素开始解析时,调用parser.nextText()方法获取下一个Text类型节点的值
》pull与sax的不同之处
1.pull读取xml文件后触发相应的事件调用方法返回的是数字。
2.pull可以在程序中控制,想解析到哪里就可以停止到哪里
3.Android中更推荐使用pull解析
》pull解析步骤
1.创建解析器对象
XmlPullParser paser = Xml.newPullParser();
2.进行解析
paser.setInput(input,"utf-8");
3.产生第一个解析事件
int eventType = paser.getEventType();
4.可以使用循环判断是否继续解析
while(eventType!=XmlPullParser.END_DOCUMENT){}
》解析实例
-------------------1。创建xml.及实例对象(Person.java)----------------略
--------------------2.pull解析(PullService .java)----------------------
List<Person> getAlPerson(InputStream is) throws XmlPullParserException, IOException{
List<Person> persons=null;
Person p=null;
XmlPullParser parser=Xml.newPullParser();
parser.setInput(is,"utf-8");
//获得事件类型
int type=parser.getEventType();
while(type!=XmlPullParser.END_DOCUMENT){
switch(type){
case XmlPullParser.START_DOCUMENT://文档开始
persons=new ArrayList<Person>();
break;
case XmlPullParser.START_TAG://元素开始
if(parser.getName().equals("user")){
p=new Person();
String id=parser.getAttributeValue(0);
p.setId(Integer.parseInt(id));
}
else if(parser.getName().equals("name")){
if(p!=null){
String name=parser.nextText();
p.setName(name);
}
}
else if(parser.getName().equals("age")){
String age=parser.nextText();
p.setAge(age);
}
break;
case XmlPullParser.END_TAG:
if("user".equals(parser.getName())){
persons.add(p);
p=null;
}
break;
}
type=parser.next();
}
return persons;
}
}
------------------------------------Activity类-----------------------------------
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
InputStream is=this.getClass().getClassLoader().getResourceAsStream("test.xml");
PullService pps=new PullService();
try {
List<Person> ps=pps.getPersons(is);
for(Person p:ps){
System.out.println(p.getId());
System.out.println(p.getName());
System.out.println(p.getAge());
}
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (XmlPullParserException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
SAX、DOM、PULL的比较
SAX、DOM、PULL各有自己的特点,具体操作XML的时候该如何选择呢?
1.内存占用
这是一个根本性问题。由于Android手机性能相对于现在的应用操作还是有限的,程序对内存的占用直接影响到了解析XML的速度。在这点上,SAX、Pull以它们比DOM占用更少的内存的解析方式,更适合于Android手机开发。
2.编程方式
SAX采用事件驱动,在相应事件触发的时候,会调用用户编写好的方法。也就是说,每解析一类XML,就要编写一个新的适合该类XML的处理类。这显然不是一个好的解决办法,尽管其在解析速度上是那么优秀。而这点,DOM因为是W3C的规范。所以被更多程序员所知道和使用。所以在开发过程中,没有太大困难。Pull虽然属于一个小众的,甚至是不为人知的解析器,但是通过上面对其介绍和示例,我们应该能看出它的简洁性。
3.访问与修改
由于采用的是流式解析,这就说明它们不能像DOM那样随机访问,XML的其中任意一个节点。并且,SAX并没有提供对文档中加节点的API,更没有删除,修改文档内容的方法。
4.访问方式
这是产生它们解析快慢的根本原因。如果把SAX和Pull比喻成一目十行,很快但是是走马观花的阅读方式的话,那么DOM就是逐字逐句的阅读,很慢,但是是过目不忘。这里还要需要注意的是,SAX,Pull解析的方式是同步的,即解析器读到哪里,就对哪里进行处理。而DOM是已经将文件解析好后,供用户提取XML中感兴趣的信息。
总结:
出于对内存占用的考虑,推荐使用SAX或者Pull来工作。可是根据它们工作的原理:如果只是需要XML最后的几个节点的相关信息,或者出现反复检索XML文件的情况。那么基本上三者在性能上就没有什么差异,反而在这时,SAX的处理类会使程序显得比其他的实现方式显得臃肿。所以,想做一个高性能的Android软件,还是要多分析,选择合适的工具,才能发挥它的作用。
Java sax、dom、pull解析xml的更多相关文章
- Android系列--DOM、SAX、Pull解析XML
您可以通过点击 右下角 的按钮 来对文章内容作出评价, 也可以通过左下方的 关注按钮 来关注我的博客的最新动态. 如果文章内容对您有帮助, 不要忘记点击右下角的 推荐按钮 来支持一下哦 如果您对文章内 ...
- Android SAX、DOM、Pull解析xml文件剖析与案例讲解
XML介绍 XML(Extensible Markup Language) 即可扩展标记语言,与HTML一样,都是SGML(Standard Generalized Markup Language,标 ...
- Android学习笔记_7_使用 sax 或者 dom 或者 pull 解析XML文件
一.Pull解析介绍: Android上使用SAX和DOM方式解析XML的方法,并且对两种做了简单的比较,通过比较我们知道对在往往内存比较稀缺的移动设备上运行的Android系统来说,SAX是一种比较 ...
- Android之Pull解析XML
一.Pull解析方法介绍 除了可以使用SAX和DOM解析XML文件,也可以使用Android内置的Pull解析器解析XML文件.Pull解析器的运行方式与SAX解析器相似.它也是事件触发的.Pull解 ...
- 使用PULL解析XML文件
转载博文1:http://blog.csdn.net/wangkuifeng0118/article/details/7313241 XmlPull和Sax类似,是基于流(stream)操作文件,然后 ...
- 转:在java中使用dom4j解析xml
JAVA 使用Dom4j 解析XML Java DOM4J Parser - Parse XML Document Dom4j下载及使用Dom4j读写XML简介 在java中使用dom4j解析xml ...
- 用DOM方式解析XML
一.用DOM方式解析XML 此例子节点结构如下: 1.获取book节点属性 (1).如果不知道节点的属性,通过 NamedNodeMap attrs = book.getAttributes(); 来 ...
- PULL解析XML的运行机制详解
PULL解析简单易上手,基本上看一遍,基本上就会解析啦,但总是感觉对PULL解析的运行机制不是很了解,就总结了以下事件驱动到底是怎么执行的.. PULL: Android内置了PULL解析器.PULL ...
- 用JAXP的dom方式解析XML文件
用JAXP的dom方式解析XML文件,实现增删改查操作 dom方式解析XML原理 XML文件 <?xml version="1.0" encoding="UTF-8 ...
随机推荐
- xml对象序列化
public static class XSerializer { /// <summary> /// 将对象序列化为xml字符串 /// </summary> /// < ...
- qt中的多线程
1.dialog.h #define DIALOG_H #include <QDialog>#include"mythread.h"namespace Ui {clas ...
- 基于Mysql数据库的SSM分页查询
前言: Hello,本Y又来了,"分页"在我们使用软件的过程中是一个很常见的场景,比如博客园对于每个博主的博客都进行了分页展示.可以简单清晰的展示数据,防止一下子将过多的数据展现给 ...
- HashMap中的散列函数、冲突解决机制和rehash
一.概述 散列算法有两个主要的实现方式:开散列和闭散列,HashMap采用开散列实现. HashMap中,键值对(key-value)在内部是以Entry(HashMap中的静态内部类)实例的方式存储 ...
- 微信小程序 sha1 实现密码加密
在utils中的util.js 文件中增加 函数 实现 字符串转换为16进制加密后的字符串 function encodeUTF8(s) { var i, r = [], c, x; for (i = ...
- .NET平台开源项目速览(20)Newlife.Core中简单灵活的配置文件
记得5年前开始拼命翻读X组件的源码,特别是XCode,但对Newlife.Core 的东西了解很少,最多只是会用用,而且用到的只是九牛一毛.里面好用的东西太多了. 最近一年时间,零零散散又学了很多,也 ...
- C语言_指针变量的赋值与运算,很详细
指针变量的赋值 指针变量同普通变量一样,使用之前不仅要定义说明, 而且必须赋予具体的值.未经赋值的指针变量不能使用, 否则将造成系统混乱,甚至死机.指针变量的赋值只能赋予地址, 决不能赋予任何其它数据 ...
- CodeForces - 681A A Good Contest
咳咳,从今天开始,每天做一个英语题,不论简单还是难,坚持到下学期的省赛,希望能有效果. 这题就是判断是否能成为red,如果他超越的人里面有在比赛前分数达到2400,并且在比赛后分数上升,那么他就能成为 ...
- easywechat--在thinkPHP5中的使用
1. 安装 1.1 v-4.0 版本要求 PHP版本在7.0以上 1.2 在项目目录下运行以下命令 若未安装composer,则先安装composer -> http://docs.phpcom ...
- WEB开发-动态验证码
1.基于Python实现,用到了django后台处理,刷新验证码功能,其他语言大同小异 2.登录界面 login.html <!DOCTYPE html> <html lang=&q ...