SAX的全稱是Simple APIs for XML,也即XML簡單應用程序接口。
使用DOM解析XML時,首先將XML文檔加載到內存當中,然後可以通過隨機的方式訪問內存中的DOM樹;SAX是基於事件而且是順序執行的,一旦經過了某個元素,我們就沒有辦法再去訪問他了,SAX不必事先將整個XML文檔加載到內存中,因此它佔據內存要比DOM小,對於大型的XML文檔來說,通常會使用SAX而不是DOM進行解析。
SAX提供的訪問模式是一種順序模式,這是一種快速讀寫XML數據的方式。當使用SAX分析器對XML文檔進行分析時,會觸發一系列事件,並激活相應的事件處理函數,應用程序通過這些事件處理函數實現對XML文檔的訪問,因而SAX接口也被稱作事件驅動接口。
SAX分析器在對XML文檔進行分析時,觸發了一系列的事件,由於事件觸發本身是有時序性的,因此,SAX提供的是一種順序訪問機制,對於已經分析過的部分,不能再倒回去重新處理。SAX之所以被叫做"簡單"應用程序接口,是因爲SAX分析器只做了一些簡單的工作,大部分工作還要由應用程序自己去做。也就是說,SAX分析器在實現時,它只是順序地檢查XML文檔中的字節流,判斷當前字節是XML語法中的哪一部分、是否符合XML語法,然後再觸發相應的事件,而事件處理函數本身則要由應用程序自己來實現。同DOM分析器相比,SAX分析器缺乏靈活性。然而,由於SAX分析器實現簡單,對內存要求比較低,因此實現效率比較高,對於那些只需要訪問XML文檔中的數據而不對文檔進行更改的應用程序來說,SAX分析器更爲合適。
SAX使用觀察者模式
1、SAX分析器的大體構成框架
圖中最上方的SAXParserFactory用來生成一個分析器實例。XML文檔是從左側箭頭所示處讀入,當分析器對文檔進行分析時,就會觸發在DocumentHandler,ErrorHandler,DTDHandler以及EntityResolver接口中定義的回調方法。
•SAX是事件驅動的,文檔的讀入過程就是SAX的解析過程。
•在讀入的過程中,遇到不同的項目,解析器會調用不同的處理方法。
2、工廠及解釋器的使用同DOM
SAXParserFactory、SAXParser
- import java.io.File;
- 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 SaxTest
- {
- public static void main(String[] args) throws Exception, SAXException
- {
- //step1:獲得SAX解析器工廠實例
- SAXParserFactory factory = SAXParserFactory.newInstance();
- //step2:獲得SAX解析器實例
- SAXParser parser = factory.newSAXParser();
- //step3:開始進行解析
- parser.parse(new File("student.xml"), new MyHandler());
- }
- }
- class MyHandler extends DefaultHandler
- {
- @Override
- public void startDocument() throws SAXException
- {
- System.out.println("parse began");
- }
- @Override
- public void endDocument() throws SAXException
- {
- System.out.println("parse end");
- }
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException
- {
- System.out.println("start element");
- }
- @Override
- public void endElement(String uri, String localName, String qName)
- throws SAXException
- {
- System.out.println("finished element");
- }
- }
解析一個XML文檔,xml文檔內容:
- <?xml version="1.0" encoding="UTF-8"?>
- <學生名冊>
- <學生 學號="1">
- <姓名>張三</姓名>
- <性別>男</性別>
- <年齡>20</年齡>
- </學生>
- <學生 學號="2">
- <姓名>李四</姓名>
- <性別>女</性別>
- <年齡>19</年齡>
- </學生>
- <學生 學號="3">
- <姓名>王五</姓名>
- <性別>男</性別>
- <年齡>21</年齡>
- </學生>
- </學生名冊>
具體的解析程序:
- import java.io.File;
- import java.util.Stack;
- import javax.xml.parsers.ParserConfigurationException;
- 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;
- @Override
- public void startElement(String uri, String localName, String qName,
- Attributes attributes) throws SAXException
- {
- stack.push(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();
- 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();
- }
- }
- }