SAX的全称是Simple APIs for XML,也即XML简单应用程序接口。与DOM不同,SAX提供的访问模式是一种顺序模式,这是一种快速读写XML数据的方式。当使用SAX分析器对XML文档进行分析时,会触发一系列事件,并激活相应的事件处理函数,应用程序通过这些事件处理函数实现对XML文档的访问,因而SAX接口也被称作事件驱动接口。
SAX分析器在对XML文档进行分析时,触发了一系列的事件,由于事件触发本身是有时序性的,因此,SAX提供的是一种顺序访问机制,对于已经分析过的部分,不能再倒回去重新处理。SAX之所以被叫做"简单"应用程序接口,是因为SAX分析器只做了一些简单的工作,大部分工作还要由应用程序自己去做。也就是说,SAX分析器在实现时,它只是顺序地检查XML文档中的字节流,判断当前字节是XML语法中的哪一部分、是否符合XML语法,然后再触发相应的事件,而事件处理函数本身则要由应用程序自己来实现。同DOM分析器相比,SAX分析器缺乏灵活性。然而,由于SAX分析器实现简单,对内存要求比较低,因此实现效率比较高,对于那些只需要访问XML文档中的数据而不对文档进行更改的应用程序来说,SAX分析器更为合适。
例子:
使用SAX开始几步和DOM使用方式一致,
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
在第23行MyHandler2类中,我们看到有3个方法,startElement、characters、endElement,这三个方法是jdk中DefaultHandler的接口的实现。
package com.sax;
import java.io.File;
import java.util.Stack;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class SaxTest2 {
public static void main(String[] args) throws Exception {
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
parser.parse(new File("student.xml"), new MyHandler2());
}
}
class MyHandler2 extends DefaultHandler {
private Stack<String> stack = new Stack<String>();
private String name;
private String gender;
private String age;
private String pre;
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException {
// stack.push(qName);
pre = qName;
for (int i = 0; i < attributes.getLength(); i++) {
String attrName = attributes.getQName(i);
String attrValue = attributes.getValue(i);
System.out.println(attrName + " = " + attrValue);
}
}
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// String tag = stack.peek();
String tag = pre;
if ("姓名".equals(tag)) {
name = new String(ch, start, length);
} else if ("性别".equals(tag)) {
gender = new String(ch, start, length);
} else if ("年龄".equals(tag)) {
age = new String(ch, start, length);
}
}
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException {
//stack.pop(); // 表示该元素已经解析完毕,需要从栈中弹出
if ("学生".equals(qName)) {
System.out.println("姓名:" + name);
System.out.println("性别:" + gender);
System.out.println("年龄:" + age);
System.out.println();
}
pre = null;
}
}
3个方法通过图片描述如下,标签开始、标签中间内容、标签结束,其他以此类推,外面的“学生”标签规则也都一直。
其中qname这个参数指xml中每个元素头的名字,详见截图。
attributes参数含义,详见截图。
具体的方法含义详见JDK,其中还包含好多其他方法,我们可以依需求进行实现。
附:
xml文件
<?xml version="1.0" encoding="utf-8"?>
<学生名册 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="student.xsd" >
<学生 学号="1">
<姓名>张三</姓名>
<性别>男</性别>
<年龄>20</年龄>
</学生>
<学生 学号="2">
<姓名>李四</姓名>
<性别>女</性别>
<年龄>19</年龄>
</学生>
<学生 学号="3">
<姓名>王五</姓名>
<性别>男</性别>
<年龄>21</年龄>
</学生>
</学生名册>
输出结果
xmlns:xsi = http://www.w3.org/2001/XMLSchema-instance
xsi:noNamespaceSchemaLocation = student.xsd
学号 = 1
姓名:张三
性别:男
年龄:20
学号 = 2
姓名:李四
性别:女
年龄:19
学号 = 3
姓名:王五
性别:男
年龄:21
注意:
截图中,该行全局变量在此方法结束后需要清空,因为是全局变量如果不清空,会影响程序后续执行,可以尝试注掉该行代码试试。