# XML編程-SAX
### 基本概述
????SAX,全稱Simple?API?for?XML,既是一種接口,也是一種軟件包。它是一種XML解析的替代方法。SAX不同于DOM解析,它逐行掃描文檔,一邊掃描一邊解析。由于應用程序只是在讀取數據時檢查數據,因此不需要將數據存儲在內存中,這對于大型文檔的解析是個巨大優勢。
????SAX是一個用于處理XML事件驅動的“推”模型,雖然它不是W3C標準,但它卻是一個得到了廣泛認可的API。SAX解析器不像DOM那樣建立一個完整的文檔樹,而是在讀取文檔時激活一系列事件,這些事件被推給事件處理器,然后由事件處理器提供對文檔內容的訪問。
PS:SAX不能夠對XML文件進行修改,刪除、添加操作。
?
### 為什么引入SAX技術?
????DOM技術也是一種非常好的DOM解析方案,為什么還會出現SAX技術呢?原因很簡單,那就是DOM是以文檔樹的結構對XML進行保存,這就表明是一次性將XML讀入內存,那么這在大型的XML文件中是不可能的。所以才產生了SAX這種掃描解析的技術。
?
### 原理圖

### SAX解析機制
? ? SAX解析允許在讀取文檔的時候,即對文檔進行處理,而不必等到整個文檔裝載完才會文檔進行操作。
????在Java中,通過繼承DefaultHandler?接口,可以開發一個SAX解析器。
????SAX的解析機制和事件監聽機制很像,都是等待某一事件觸發,然后調用相應方法。
????SAX解析器的最常用5個事件:
1、startDocument():這標識著SAX解析器掃描到文檔開始位置。
2、endDocument(),這標識著SAX解析器掃描到文檔的結束位置。
3、startElement(),這標識著SAX解析器掃描到一個元素的開始標簽。
4、character(),這標識著SAX解析器掃描到了一些文本,注意它是以char數組形式存放的。
5、endElement(),這標識著SAX解析器掃描到了一個元素的結束標簽。
?
### 事件處理器常用方法參數列表
public?void?startDocument()
?
public?void?startElement(String?uri,?String?localName,?String?qName,Attributes?attributes)?
uri?-?名稱空間?URI,如果元素沒有任何名稱空間?URI,或者沒有正在執行名稱空間處理,則為空字符串。
localName?-?本地名稱(不帶前綴),如果沒有正在執行名稱空間處理,則為空字符串。
qName?-?限定的名稱(帶有前綴),如果限定的名稱不可用,則為空字符串。
attributes?-?附加到元素的屬性。如果沒有屬性,則它將是空的?Attributes?對象。
?
public?void?characters(char[]?ch,?int?start,?int?length)
ch?-?文檔的所有字符。
start?-?字符數組中的開始位置。
length?-?從字符數組中使用的字符數。?
?
public?void?endElement(String?uri,?String?localName,?String?qName)
uri?-?名稱空間?URI,如果元素沒有任何名稱空間?URI,或者沒有正在執行名稱空間處理,則為空字符串。
localName?-?本地名稱(不帶前綴),如果沒有正在執行名稱空間處理,則為空字符串。
qName?-?限定的名稱(帶有前綴),如果限定的名稱不可用,則為空字符串。?
?
public?void?endDocument()
?
### 解析方式
????通過解析器和事件處理器一起使用,可以解析XML文檔。解析器可以使用JAXP的API創建,創建出SAX解析器后,就可以指定解析器去解析某個XML文檔。事件處理器由程序員編寫,程序員通過事件處理器中方法的參數,就可以很輕松地得到sax解析器解析到的數據,從而可以決定如何對數據進行處理。
?
解析步驟
1、通過調用SAXParserFactory的newInstance()方法獲得Sax解析器工廠對象。
2、通過Sax解析器工廠對象調用newSAXParser()方法獲得解析器SAXParser對象
3、通過調用解析器對象的parse方法將解析器與事件處理器對象關聯
?
?
案例:
**XML6.xml**
~~~
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<班級 班次="1班" 編號="C1">
<學生 地址="湖南" 學號="n1" 性別="男" 授課方式="面授" 朋友="n2" 班級編號="C1">
<名字>張三</名字>
<年齡>20</年齡>
<介紹>不錯</介紹>
</學生>
<學生 學號="n2" 性別="女" 授課方式="面授" 朋友="n1 n3" 班級編號="C1">
<名字>李四</名字>
<年齡>18</年齡>
<介紹>很好</介紹>
</學生>
<學生 學號="n3" 性別="男" 授課方式="面授" 朋友="n2" 班級編號="C1">
<名字>王五</名字>
<年齡>22</年齡>
<介紹>非常好</介紹>
</學生>
<學生 性別="男">
<名字>小明</名字>
<年齡>30</年齡>
<介紹>好</介紹>
</學生>
</班級>
~~~
~~~
package com.pc;
import javax.xml.parsers.*;
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
public class XML6{
//使用sax技術去解析xml文件
public static void main(String[] args) throws Exception, SAXException {
// TODO Auto-generated method stub
//1.創建SaxParserFactory
SAXParserFactory spf=SAXParserFactory.newInstance();
//2.創建SaxParser 解析器
SAXParser saxParser=spf.newSAXParser();
//3 把xml文件和事件處理對象關聯
saxParser.parse("src/com/pc/XML6.xml",new MyDefaultHandler2() );
}
}
// 只顯示學生的名字和年齡
class MyDefaultHandler2 extends DefaultHandler{
private boolean isName=false;
private boolean isAge=false;
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
// TODO Auto-generated method stub
String con=new String(ch,start,length);
if(!con.trim().equals("")&&(isName||isAge)){
System.out.println(con);
}
isName=false;
isAge=false;
//super.characters(ch, start, length);
}
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
super.endDocument();
}
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, name);
}
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
super.startDocument();
}
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
if(name.equals("名字")){
this.isName=true;
}else if(name.equals("年齡")){
this.isAge=true;
}
}
}
//定義事件處理類
class MyDefaultHandler1 extends DefaultHandler{
//發現文檔開始
@Override
public void startDocument() throws SAXException {
// TODO Auto-generated method stub
System.out.println("startDocument()");
super.startDocument();
}
//發現xml文件中的一個元素
@Override
public void startElement(String uri, String localName, String name,
Attributes attributes) throws SAXException {
// TODO Auto-generated method stub
System.out.println("元素名稱="+name);
}
//發現xml文件中的文本
@Override
public void characters(char[] ch, int start, int length)
throws SAXException {
String con=new String(ch,start,length);
//顯示文本內容:
if(!con.trim().equals("")){
System.out.println(new String(ch,start,length));
}
}
//發現xml文件中一個元素介紹</xx>
@Override
public void endElement(String uri, String localName, String name)
throws SAXException {
// TODO Auto-generated method stub
super.endElement(uri, localName, name);
}
//發現文檔結束
@Override
public void endDocument() throws SAXException {
// TODO Auto-generated method stub
System.out.println("endDocument()");
super.endDocument();
}
}
~~~