SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。

与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。

当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口

  局限性:

  1. SAX分析器在对XML文档进行分析时,触发了一系列的事件,由于事件触发本身是有时序性的,因此,SAX提供的是一种顺序访问机制,对于已经分析过的部分,不能再倒回去重新处理。

  即,一旦经过了某个元素,我们没有办法返回去再去访问它。

  2. SAX分析器只做了一些简单的工作,大部分工作还要由应用程序自己去做。

  也就是说,SAX分析器在实现时,只是顺序地检查XML文档中的字节流,判断当前字节是XML语法中的哪一部分、是否符合XML语法,然后再触发相应的事件,而事件处理函数本身则要由应用程序自己来实现。

  同DOM分析器相比,SAX分析器缺乏灵活性。

  优势:

  然而,由于SAX分析器实现简单,对内存要求比较低,(SAX不必将整个XML文档加载到内存当中,因此它占据内存要比DOM小), 因此实现效率比较高。

  对于大型的XML文档来说,通常会用SAX而不是DOM。

  并且对于那些只需要访问XML文档中的数据而不对文档进行更改的应用程序来说,SAX分析器更为合适。

SAX分析器

  XML解析器实际上就是一段代码,它读入一个XML文档并分析其结构。

  分类:

  带校验的解析器

  不校验的解析器(效率高)

  支持DOM的解析器(W3C的官方标准)

  支持SAX的解析器(事实上的工业标准)

  SAX是事件驱动的,文档的读入过程就是SAX的解析过程。

  在读入的过程中,遇到不同的项目,解析器会调用不同的处理方法。

【XML文件内容】

<?xml version = "1.0" encoding = "UTF-8"?>
<students>
<student id="1">
<name>tonyliu</name>
<age>19</age>
<sex>男</sex>
<group>
<id>1</id>
<name>Group1</name>
</group>
</student>
<student id="2">
<name>Susywang</name>
<age>18</age>
<sex>女</sex>
<group>
<id>2</id>
<name>Group2</name>
</group>
</student> <student id="3">
<name>JackZhang</name>
<age>35</age>
<sex>男</sex>
<group>
<id>3</id>
<name>Group3</name>
</group>
</student>
</students>

【SAX 解析代码】

根据xml文件内容分为2个类,一个是Student类另一个为Group类,分别记入相对应的字段。

再定义一个枚举,分别存入一些常量,方便调用。这里要注意的是,仔细看一下xml内容,会发现Student以及group类中都包含了id跟name的字段。所以当我们在写代码中为了让计算机清楚的知道我们指的name,id到底是Student中的还是Group中的,要通过Enum定义的常量来区分。

package Entity;

public class Student {

    private int id;
private String name;
private int age;
private String sex;
private Group group;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Group getGroup() {
return group;
}
public void setGroup(Group group) {
this.group = group;
}
public Student(int id, String name, int age, String sex, Group group) {
super();
this.id = id;
this.name = name;
this.age = age;
this.sex = sex;
this.group = group;
}
public Student() {
super();
// TODO Auto-generated constructor stub
}
@Override
public String toString() {
return "Student [age=" + age + ", group=" + group + ", id=" + id
+ ", name=" + name + ", sex=" + sex + "]";
} }

Student 类

package Entity;

public class Group {

    private int id;
private String name;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Group() {
super();
// TODO Auto-generated constructor stub
}
public Group(int id, String name) {
super();
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Group [id=" + id + ", name=" + name + "]";
} }

Group 类

package Tool;

public enum StudentEnum {

    stuName,age,sex,groupId,groupName,none

}

Enum(枚举)

package Tool;

import java.util.ArrayList;
import java.util.List; import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler; import Entity.Group;
import Entity.Student; //继承DefaultHandler这个类,为了使用startDocument,startElement,charecter,endelement,enddocument方法 public class StudentParser extends DefaultHandler{ private List<Student> students = null; //创建一个集合方便存放数据
private boolean isgroupState = false; //定义标签区分group以及student中的id,name这样的相同字段。因为只有2个类因此boolean类型即可
private StudentEnum state = StudentEnum.none; //把枚举的状态设置为none
private Group group = null; //初始化Group类
private Student student = null; //初始化Student类 //设定一个集合方法为了方便外层调用students这个集合中的内容
public List<Student> getResult(){
return this.students;
} @Override
public void startDocument() throws SAXException {
students = new ArrayList<Student>(); //初始化集合
}
@Override
public void startElement(String uri, String localName, String qName,
Attributes attrs) throws SAXException {
//通过startElement方法中的qName来指定xml内容中的student字段
if(qName.equals("student")){
String stuId = attrs.getValue("id"); //<Student>的属性只有一个id,因此通过attrs.getValue这个方法获取到id属性
student = new Student(); //很重要,很重要,很重要。这里一定要初始化Student这个类,为了就是下面通过.setId方法来指定id值
student.setId(Integer.parseInt(stuId));
}
if(qName.equals("name")){
//这里就看出来Enum的重要性了。如果是我们上面设定的isgroupState的话就调用Enum类中的group相关字段。相反就调用Enum类中Student相关常量
if(isgroupState)
state = StudentEnum.groupName;
else
state = StudentEnum.stuName; return;
}
if(qName.equals("age")){
state = StudentEnum.age; //把状态标注为枚举中的age
return;
}
if(qName.equals("sex")){
state = StudentEnum.sex; //同上
return;
}
if(qName.equals("group")){
group = new Group(); //如果为group那么先要初始化Group这个类,方便调用group类中的方法
isgroupState = true; //因为默认isgroupState的状态为false。这里如果是group那么自然状态就变成了true
return;
}
//group类中只有2个字段,而name在我们上述中已经有了判断。那么id跟Student一样先判断qName是否是id,再判断是否是groupState中的id,如果是就把state状态标注成Enum中的groupId.
if(qName.equals("id")){
if(isgroupState){
state = StudentEnum.groupId;
return;
}
} }
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
if(state == StudentEnum.none){
return;
}
//定义一个String类,存放characters方法中给出了三个参数.
String str = new String(ch,start,length);
//通过switch ,case分别把每个字段记录进去并通过student,group类中的set方法来进行设定。设定完毕后一定要把每个状态标注成none
switch (state) {
case stuName:
student.setName(str);
state = StudentEnum.none;
break;
case age:
student.setAge(Integer.parseInt(str));
state = StudentEnum.none;
break;
case sex:
student.setSex(str);
state = StudentEnum.none;
break;
case groupId:
group.setId(Integer.parseInt(str));
state = StudentEnum.none;
break;
case groupName:
group.setName(str);
state = StudentEnum.none;
break; default:
break;
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//这里是指在什么节点结束。xml内容我们是以</group></Student>为结束的因此这里还是根据qName来判断并标注状态。
if(qName.equals("group")){
isgroupState = false;
student.setGroup(group); //通过student类中的.setGroup方法把group中的内容追加到Student类中
return;
}
if(qName.equals("student")){
students.add(student); //最后把student类中的内容全部加载到students这个集合中
return;
}
}
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
} }

StudentParser

StudentParser这个类中内容是我们SAX解析中的重点。同DOM一样也是一个解析器,通过逐步读取数据的方式进行解析不需要一下子把数据读取到内容中后再解析。

【Test测试】

package View;

import java.io.IOException;
import java.util.List; import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory; import org.xml.sax.SAXException; import Entity.Student;
import Tool.StudentParser; public class Test { public static void main(String[] args) throws ParserConfigurationException, SAXException, IOException {
                //调用SAXParserFactory以及SAXParer工厂类。
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
StudentParser handler = new StudentParser();  //初始化我们的解析器 parser.parse("C:/Users/IBM_ADMIN/Desktop/xml/student.xml", handler);//通过parser.parse方法指定文件地址以及加载我们的解析器 List<Student> students = handler.getResult();  //调用解析中的.getResult方法来调用students集合中的内容。
//循环这个集合并打印
for(Student stu:students){
System.out.println(stu);
} } }

【结果】

下面结果可以看出我们成功的对XML文件中的内容进行了解析。日后比如说有个Group4,并有了新的成员的情况下,我们也不需要再重写我们的代码。只要xml结构不变,那么内容也会自动的被读取。

Student [age=19, group=Group [id=1, name=Group1], id=1, name=tonyliu, sex=男]
Student [age=18, group=Group [id=2, name=Group2], id=2, name=Susywang, sex=女]
Student [age=35, group=Group [id=3, name=Group3], id=3, name=JackZhang, sex=男]

【文件处理】xml 文件 SAX解析的更多相关文章

  1. schema文件及XML文件的DOM和Sax解析

    schema文件 <?xml version="1.0" encoding="UTF-8"?> <schema xmlns="htt ...

  2. LINQ to XML 从逗号分隔值 (CSV) 文件生成 XML 文件

    参考:http://msdn.microsoft.com/zh-cn/library/bb387090.aspx 本示例演示如何使用 语言集成查询 (LINQ) 和 LINQ to XML 从逗号分隔 ...

  3. web端自动化——Python读取txt文件、csv文件、xml文件

    1.读取txt文件 txt文件是我们经常操作的文件类型,Python提供了以下几种读取txt文件的方式. 1)read(): 读取整个文件. 2)readline(): 读取一行数据. 3)readl ...

  4. 关于跨域策略文件crossdomain.xml文件

    下载flexpaper源码修改后做成swf阅读器,要加入待阅读的swf文件,可以在flex里调用js的方法来获取swf文件的路径的方法,在js只专注获取路径就行,等着flex来调用:但这里会遇到一个问 ...

  5. android-pull方式解析xml文件以及XML文件的序列化

    android解析XML ---------------------------基础要像磐石 在android平台上可以使用SAX.DOM和自带的Pull解析器解析xml文件,本文主要介绍使用pull ...

  6. Java文件操作①——XML文件的读取

    一.邂逅XML 文件种类是丰富多彩的,XML作为众多文件类型的一种,经常被用于数据存储和传输.所以XML在现今应用程序中是非常流行的.本文主要讲Java解析和生成XML.用于不同平台.不同设备间的数据 ...

  7. 使用jaxp对比xml进行SAX解析

    package cn.itcast.sax; import java.io.IOException; import javax.xml.parsers.ParserConfigurationExcep ...

  8. xml的SAX解析和dom解析的区别

    一,区别 DOM解析 SAX解析 原理: 一次性加载xml文档,不适合大容量的文件读取 原理: 加载一点,读取一点,处理一点.适合大容量文件的读取 DOM解析可以任意进行增删改成 SAX解析只能读取 ...

  9. xml的SAX解析规则

    一,为什么要用它 1.1,讲解 DOM解析原理:一次性把xml文档加载进内存,然后在内存中构建Document树. 对内存要求比较要. 缺点: 不适合读取大容量的xml文件,容易导致内存溢出. SAX ...

  10. XML之SAX解析模型

    DOM解析会把整个XML文件全部映射成Document里的树形结构,当遇到比较大的文件时,它的内存占用很大,查找很慢 SAX就是针对这种情况出现的解决方案,SAX解析器会从XML文件的起始位置起进行解 ...

随机推荐

  1. 栅格那点儿事(四B)---多波段栅格数据的显示

    多波段栅格数据的显示 我上面说了这么多,可能有的人会觉得平时也根本用不上.自然,说起影像数据,大家接触到对多的就是最最常见的航片或卫片.对于这种栅格数据呢,大多数的场景下,都只需实现一个效果,就是最接 ...

  2. python模块详解 sys shutil

    sys模块 sys.argv 命令行参数List,第一个元素是程序本身路径 sys.exit(n) 退出程序,正常退出时exit(0) sys.version 获取Python解释程序的版本信息 sy ...

  3. tnagios - query handler

    启动日志 [root@bjyh-48-86 nagios]# cat nagios.log [1433471109] Nagios 4.1.0rc1 starting... (PID=5136) [1 ...

  4. head头部内放些什么标签?

    前言 在学html时,在头部标签内除了知道可以放title标签外,不知道还可以放什么标签,一脸迷茫后赶快去百度,然后小笔记记起来,整理一番. 关键字 <title>  <meta&g ...

  5. Linux安装中文字体包

    进入rhel5.5安装盘/Server路径找到字体安装包: fonts-chinese-3.02-12.el5.noarch.rpm fonts-ISO8859-2-75dpi-1.0-17.1.no ...

  6. Windows Python 版本切换工具 --- Switch Python Version Tool For Windows

    2018年1月13日 更新: 如果要用到不同版本的Python 请使用 virtualenv, pip install virtualenv  , 我做的这个工具可以拿来维护下环境变量~~ 填好路径自 ...

  7. 关于(void**)及其相关的理解

    #define LOADBASSFUNCTION (f) *((void **)&f)=(void*)GetProcAddress (hBass,# f) 这一句话使用*((void**)&a ...

  8. React的安装

    创建: 2019/05/01 完成: 2019/05/01 create-react-app  学习及创建单页app npx create-react-app my-app cd my-app npm ...

  9. theano中tensor的构造方法

    import theano.tensor as T x = T.scalar('myvar') myvar = 256 print type(x),x,myvar 运行结果: <class 't ...

  10. 测试 jdbc 中连接关闭的时机

    测试 jdbc 中连接关闭的时机 写一段程序,测试 jdbc 连接的关闭情况 /** * 测试 jdbc 连接的关闭情况 */ public static void testOpenCon(){ // ...