在java中,原生解析xml文檔的方式有兩種,分別是: Dom解析和Sax解析
Dom解析功能強大,可增刪改查,操作時會將xml文檔以文檔物件的方式讀取到記憶體中,因此適用於小文檔
Sax解析是從頭到尾逐行逐行逐行讀取內容,修改較為不便,但適用於唯讀的大文檔
本文主要講解Sax解析,其餘放在後面
Sax採用事件驅動的方式解析文件。簡單點說,如同在電影院看電影一樣,從頭到尾看一遍就完了,不能回退(Dom可來來回回讀取)
在看電影的過程中,每遇到一個情節,一段淚水,一次擦肩,你都會調動大腦和神經去接收或處理這些訊息
同樣,在Sax的解析過程中,讀取到文檔開頭、結尾,元素的開頭和結尾都會觸發一些回調方法,你可以在這些回調方法中進行相應事件處理
這四個方法分別是: startDocument() 、endDocument()、 startElement()、 endElement
此外,光讀取到節點處是不夠的,我們還需要characters()方法來仔細處理元素內所包含的內容
將這些回呼方法集合起來,便形成了一個類,這個類也就是我們需要的觸發器
一般從Main方法讀取文檔,卻在觸發器中處理文檔,這就是所謂的事件驅動解析方法
如上圖,在觸發器中,首先開始讀取文檔,然後開始逐一解析元素,每個元素中的內容會返回到characters()方法
接著結束元素讀取,所有元素讀取完後,結束文件解析
現在我們開始建立觸發器這個類,要建立這個類別首先需要繼承DefaultHandler
建立SaxHandler,並覆寫對應方法:
public class SaxHandler extends DefaultHandler {
/* 此方法有三個參數
arg0是傳回的字元數組,其包含元素內容
arg1和arg2分別是陣列的開始位置和結束位置*/
@Override
public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
String content = new String(arg0, arg1, arg2);
System.out.println(content);
super.characters(arg0, arg1, arg2);
}
@Override
public void endDocument() throws SAXException {
System.out.println("/n…………結束解析文件…………");
super.endDocument();
}
/* arg0是名稱空間
arg1是包含名稱空間的標籤,如果沒有名稱空間,則為空
arg2是不包含名稱空間的標籤*/
@Override
public void endElement(String arg0, String arg1, String arg2)
throws SAXException {
System.out.println("結束解析元素" + arg2);
super.endElement(arg0, arg1, arg2);
}
@Override
public void startDocument() throws SAXException {
System.out.println("…………開始解析文件…………/n");
super.startDocument();
}
/*arg0是名稱空間
arg1是包含名稱空間的標籤,如果沒有名稱空間,則為空
arg2是不包含名稱空間的標籤
arg3很明顯是屬性的集合*/
@Override
public void startElement(String arg0, String arg1, String arg2,
Attributes arg3) throws SAXException {
System.out.println("開始解析元素" + arg2);
if (arg3 != null) {
for (int i = 0; i < arg3.getLength(); i++) {
// getQName()是取得屬性名稱,
System.out.print(arg3.getQName(i) + "=/"" + arg3.getValue(i) + "/"");
}
}
System.out.print(arg2 + ":");
super.startElement(arg0, arg1, arg2, arg3);
}
}
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
public class TestDemo {
public static void main(String[] args) throws Exception {
// 1.實例化SAXParserFactory對象
SAXParserFactory factory = SAXParserFactory.newInstance();
// 2.建立解析器
SAXParser parser = factory.newSAXParser();
// 3.取得需要解析的文檔,產生解析器,最後解析文檔
File f = new File("books.xml");
SaxHandler dh = new SaxHandler();
parser.parse(f, dh);
}
}
開始解析元素books
books:
開始解析元素book
id="001"book:
開始解析元素title
title:Harry Potter
結束解析元素title
開始解析元素author
author:J K. Rowling
結束解析元素author
結束解析元素book
開始解析元素book
id="002"book:
開始解析元素title
title:Learning XML
結束解析元素title
開始解析元素author
author:Erik T. Ray
結束解析元素author
結束解析元素book
結束解析元素books
…………結束解析文檔…………
為了更清晰的執行此流程,我們還可以重寫SaxHandler,使其將原先的xml文件還原一遍
重寫的SaxHandler類別:
public class SaxHandler extends DefaultHandler {
@Override
public void characters(char[] arg0, int arg1, int arg2) throws SAXException {
System.out.print(new String(arg0, arg1, arg2));
super.characters(arg0, arg1, arg2);
}
@Override
public void endDocument() throws SAXException {
System.out.println("/n結束解析");
super.endDocument();
}
@Override
public void endElement(String arg0, String arg1, String arg2)
throws SAXException {
System.out.print("</");
System.out.print(arg2);
System.out.print(">");
super.endElement(arg0, arg1, arg2);
}
@Override
public void startDocument() throws SAXException {
System.out.println("開始解析");
String s = "<?xml version=/"1.0/" encoding=/"UTF-8/"?>";
System.out.println(s);
super.startDocument();
}
@Override
public void startElement(String arg0, String arg1, String arg2,
Attributes arg3) throws SAXException {
System.out.print("<");
System.out.print(arg2);
if (arg3 != null) {
for (int i = 0; i < arg3.getLength(); i++) {
System.out.print(" " + arg3.getQName(i) + "=/"" + arg3.getValue(i) + "/"");
}
}
System.out.print(">");
super.startElement(arg0, arg1, arg2, arg3);
}
}
現在看起來好多了,將其還原更能充分說明其解析流程