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
注意:
截图中,该行全局变量在此方法结束后需要清空,因为是全局变量如果不清空,会影响程序后续执行,可以尝试注掉该行代码试试。