1. 程式人生 > >sax的解析原理基礎

sax的解析原理基礎

sax sax解析 xml的解析方式 xml

1:sax解析是什麽?

SAX(simple API for XML)是一種XML解析的替代方法。相比於DOM,SAX是一種速度更快,更有效的方法。它逐行掃描文檔,一邊掃描一邊解析。而且相比於DOM,SAX可以在解析文檔的任意時刻停止解析,但任何事物都有其相反的一面,對於SAX來說就是操作復雜。

2:SAX解析和DOM解析的區別?

JAVA 解析 XML 通常有兩種方式:DOM 和SAX。DOM(文檔對象模型)是W3C標準,提供了標準的解析方式,但其解析效率一直不盡如人意,這是因為DOM解析XML文檔時,把所有內容一次性的裝載入內存,並構建一個駐留在內存中的樹狀結構(節點數)。如果需要解析的XML文檔過大,或者我們只對該文檔中的一部分感興趣,這樣就會引起性能問題。


3:工作原理

編輯

SAX,它既是一個接口,也是一個軟件包.但作為接口,SAX是事件驅動型XML解析的一個標準接口不會改變 SAX的工作原理簡單地說就是對文檔進行順序掃描,當掃描到文檔(document)開始與結束、元素(element)開始與結束、文檔(document)結束等地方時通知事件處理函數,由事件處理函數做相應動作,然後繼續同樣的掃描,直至文檔結束。

大多數SAX都會產生以下類型的事件:

1.在文檔的開始和結束時觸發文檔處理事件。

2.在文檔內每一XML元素接受解析的前後觸發元素事件。

3.任何元數據通常由單獨的事件處理

4.在處理文檔的DTD或Schema時產生DTD或Schema事件。

5.產生錯誤事件用來通知主機應用程序解析錯誤。


4:SAX解析過程

編輯

對於一個XML文檔舉例來說

<doc>

<para>Hello,World!</para>

</doc>

其解析的過程為:

1.start document

2.start element:doc......

3.start element:para.....

4.characters:Hello,World!

5.end element:para......

6.end element;doc......

7.end document

對於解析過程中的每一步都會有事件發生,都會觸發相應接口中的事件處理程序。

編寫程序的步驟為:

(1).創建事件處理程序(也就是編寫ContentHandler的實現類,一般繼承自DefaultHandler類,采用adapter模式)

(2).創建SAX解析器

(3).將事件處理程序分配到解析器

(4).對文檔進行解析,將每個事件發送給事件處理程序


5:SAX 模型的解析過程

編輯

過程:

1.首先SAXParserFactory來創建一個SAXParserFactory實例

SAXParserFactory factory = SAXParserFactory.newInstance();

2.根據SAXParserFactory實例來創建SAXParser

3.SAXParser產生SAXReader

XMLReader reader = factory.newSAXParser().getXMLReader();

4.XMLReader 加載XML,然後解析XML,在解析的過程中觸發相對於接口中的事件處理程序


6:接口介紹

編輯

ContentHandler接口 (主要用到的接口)

ContentHandler是Java類包中一個特殊的SAX接口,位於org.xml.sax包中。該接口封裝了一些對事件處理的方法,當XML解析器開始解析XML輸入文檔時,它會遇到某些特殊的事件,比如文檔的開頭和結束、元素開頭和結束、以及元素中的字符數據等事件。當遇到這些事件時,XML解析器會調用ContentHandler接口中相應的方法來響應該事件。

ContentHandler接口的方法有以下幾種:

void startDocument()//文件打開時調用

void endDocument()//當到文檔的末尾調用

void startElement(String uri, String localName, String qName, Attributes atts)//當遇到開始標記時調用

void endElement(String uri, String localName, String qName)//當遇到節點結束時調用

void characters(char[ ] ch, int start, int length)//當分析器遇到無法識別為標記或者指令類型字符時調用

DTDHandler接口

DTDHandler用於接收基本的DTD相關事件的通知。該接口位於org.xml.sax包中。此接口僅包括DTD事件的註釋和未解析的實體聲明部分。SAX解析器可按任何順序報告這些事件,而不管聲明註釋和未解析實體時所采用的順序;但是,必須在文檔處理程序的startDocument()事件之後,在第一個startElement()事件之前報告所有的DTD事件。

DTDHandler接口包括以下兩個方法

void startDocumevoid notationDecl(String name, String publicId, String systemId) nt()

void unparsedEntityDecl(String name, String publicId, String systemId, String notationName)

EntityResolver接口

EntityResolver接口是用於解析實體的基本接口,該接口位於org.xml.sax包中。

該接口只有一個方法,如下:

public InputSource resolveEntity(String publicId, String systemId)

解析器將在打開任何外部實體前調用此方法。此類實體包括在DTD內引用的外部DTD子集和外部參數實體和在文檔元素內引用的外部通用實體等。如果SAX應用程序需要實現自定義處理外部實體,則必須實現此接口。

ErrorHandler接口

ErrorHandler接口是SAX錯誤處理程序的基本接口。如果SAX應用程序需要實現自定義的錯誤處理,則它必須實現此接口,然後解析器將通過此接口報告所有的錯誤和警告。

該接口的方法如下:

void error(SAXParseException exception)

void fatalError(SAXParseException exception)

void warning(SAXParseException exception)


SAX的解析舉例說明

import java.io.IOException;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

public class Demo1 {
	/*
	 * SAX解析XML文檔
	 * */
	public static void main(String[] args) throws SAXException, ParserConfigurationException, IOException {
		//1:創建解析工廠
		SAXParserFactory factory = SAXParserFactory.newInstance();
		
		//2:得到解析器
		SAXParser sp = factory.newSAXParser();
		
		//3:得到讀取器
		XMLReader reader = sp.getXMLReader();
		
		//4:設置內容處理器
		reader.setContentHandler(new ListHandler());
		
		//5:讀取XML文檔內容
		reader.parse("src/book.xml");
	}

}
	//得到XML文檔的所有內容
class ListHandler implements ContentHandler{   //需要實現接口內容

	@Override
	public void setDocumentLocator(Locator locator) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void startDocument() throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void endDocument() throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void startPrefixMapping(String prefix, String uri)
			throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void endPrefixMapping(String prefix) throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes atts) throws SAXException {
		System.out.println("<"+qName+">");
		for(int i =0; atts!=null && i<atts.getLength();i++){
			String attName = atts.getQName(i);
			String attValue = atts.getValue(i);
			System.out.println(attName+"--"+attValue);
			}
	}

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		System.out.println("</"+qName+">");
		
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		System.out.println(new String(ch, start,length));
		
	}

	@Override
	public void ignorableWhitespace(char[] ch, int start, int length)
			throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void processingInstruction(String target, String data)
			throws SAXException {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void skippedEntity(String name) throws SAXException {
		// TODO Auto-generated method stub
		
	}
	
}


//獲取指定標簽的值
class TagValueHandler extends DefaultHandler {
	private String currentTag;	//記住當前解析到的是什麽標簽
	private int needNumber = 2;		//記住想獲取第幾個作者標簽的值
	private int currentNumber; 		//當前解析到第幾個
	@Override
	public void startElement(String uri, String localName, String qName,
			Attributes attributes) throws SAXException {
		currentTag = qName;
		if(currentTag.equals("作者")){
			currentNumber++;
		}
	}
	

	@Override
	public void endElement(String uri, String localName, String qName)
			throws SAXException {
		// TODO Auto-generated method stub
		super.endElement(uri, localName, qName);
	}

	@Override
	public void characters(char[] ch, int start, int length)
			throws SAXException {
		if("作者".equals(currentTag) && currentNumber ==needNumber){
			System.out.println(new String(ch,start,length));
		}
	}

}

sax的解析原理基礎