SAX,全称Simple API for XML,既是一种
接口,也是一种
软件包。它是一种XML解析的替代方法。SAX不同于DOM解析,它逐行扫描文档,一边扫描一边解析。由于应用程序只是在读取数据时检查数据,因此不需要将数据存储在内存中,这对于大型文档的解析是个巨大优势。
简介
SAX是一个用于处理XML
事件驱动的“推”模型,虽然它不是
W3C标准,但它却是一个得到了认可的API。
SAX解析器不像DOM那样建立一个完整的文档树,而是在读取文档时激活一系列事件,这些事件被推给事件处理器,然后由事件处理器提供对文档内容的访问。
常见的事件处理器有三种基本类型:
● 用于访问XML DTD内容的DTDHandler;
● 用于低级访问解析错误的ErrorHandler;
● 用于访问文档内容的ContentHandler,这也是最普遍使用的事件处理器。
SAX解析器读取输入文档并在处理文档时将每个事件推给文档处理器(MyContentHandler)。与DOM相比,
SAX解析器能提供更好的性能优势,它提供对XML文档内容的有效低级访问。SAX模型最大的优点是内存消耗小,因为整个文档无需一次加载到内存中,这使SAX解析器可以解析大于
系统内存的文档。另外,你无需像在DOM中那样为所有节点创建对象。最后,SAX“推”模型可用于广播环境,能够同时注册多个ContentHandler,并行接收事件,而不是在一个管道中一个接一个地进行处理。
SAX的缺点是你必须实现多个事件处理程序以便能够处理所有到来的事件,同时你还必须在应用程序代码中维护这个事件状态,因为
SAX解析器不能交流元信息,如DOM的父/子支持,所以你必须跟踪解析器处在文档层次的哪个位置。如此一来,你的文档越复杂,你的应用逻辑就越复杂。虽然没有必要一次将整个文档加载到内存中,但SAX解析器仍然需要解析整个文档,这点和DOM一样。
也许SAX面临的最大问题是它没有内置如XPath所提供的那些导航支持。再加上它的单遍解析,使它不能支持随机访问。这一限制也表现在名字空间上: 对有继承名字空间的元素不做注解。这些限制使SAX很少被用于操作或修改文档。
那些只需要单遍读取内容的应用程序可以从SAX解析中大大受益。很多B2B和EAI应用程序将XML用做
封装格式,接收端用这种格式简单地接收所有数据。这就是SAX明显优于DOM的地方:因高效而获得高吞吐率。在SAX 2.0 中有一个内置的过滤机制,可以很轻松地输出一个文档子集或进行简单的文档转换。
SAX
SAX,全称Simple API for XML,既是指一种接口,也是指一个软件包。SAX最初是由David Megginson采用
Java语言开发,之后SAX很快在Java开发者中流行起来。San现在负责管理其原始API的开发工作,这是一种公开的、
开放源代码软件。不同于其他大多数XML标准的是,SAX没有语言开发商必须遵守的标准SAX参考版本。因此,SAX的不同实现可能采用区别很大的接口。
作为接口,SAX是
事件驱动型XML解析的一个标准接口(standard interface)不会改变,已被OASIS(Organization for the Advancement of Structured Information Standards)所采纳。作为软件包,SAX最早的开发始于1997年12月,由一些在互联网上分散的程序员合作进行。后来,参与开发的程序员越来越多,组成了互联网上的XML-DEV社区。五个月以后,1998年5月,SAX 1.0版由XML-DEV正式发布。目前,最新的版本是SAX 2.0。2.0版本在多处与1.0版本不兼容,包括一些类和方法的名字。
原理
SAX的工作原理简单地说就是对文档进行顺序扫描,当扫描到文档(document)开始与结束、元素(element)开始与结束、文档(document)结束等地方时通知
事件处理函数,由事件处理函数做相应动作,然后继续同样的扫描,直至文档结束。
大多数SAX实现都会产生以下类型的事件:
在文档的开始和结束时触发文档处理事件。
在文档内每一XML元素接受解析的前后触发元素事件。
任何元数据通常都由单独的事件交付。
在处理文档的DTD或Schema时产生DTD或Schema事件。
产生错误事件用来通知主机应用程序解析错误。
SAX的优缺点
常用接口介绍
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)
(1)用系统默认值来创建一个XMLReader(解析器):
XMLReader reader = XMLReaderFactory.createXMLReader();
(2)从给定的类名称来创建一个XMLReader :
XMLReader reader = XMLReaderFactory.createXMLReader(
org.apache.xerces.parsers.SAXParser);
(3)使用javax.xml.parsers包中的SAXParserFactory类和SAXParser类创建:
SAXParserFactory spFactory = SAXParserFactory.newInstance();
SAXParser sParser = spFactory.newSAXParser();
DefaultHandler类
DefaultHandler类是SAX2事件处理程序的默认基类。它实现了EntityResolver、DTDHandler、ContentHandler和ErrorHandler这四个接口。包含这四个接口的所有方法,所以我们在编写事件处理程序时,可以不用直接实现这四个接口,而继承该类,然后重写我们需要的方法。如下:
import org.xml.sax.helpers.DefaultHandler;
public class TestDefaultHandler extends DefaultHandler{
public void startDocument() throws SAXException{
System.out.println(开始解析!); }
public void endDocument() throws SAXException{
System.out.println(解析完成!); }
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
System.out.println(元素名:+qName);
}
public void endElement(String uri, String localName, String qName)
throws SAXException{
System.out.println(对+qName+的解析完成!);
}
}
XMLReader接口
XMLReader接口是使用回调读取XML文档的接口。XMLReader是
XML解析器的SAX2驱动程序必须实现的接口。此接口允许应用程序设置和查询解析器中的功能和属性,注册文档的事件处理程序,以及对文档的解析。如下:
import org.xml.sax.*;
public class TestXMLReader{
public TestXMLReader(){
try{
XMLReader reader = XMLReaderFactory.createXMLReader(
org.apache.xerces.parsers.SAXParser);
System.out.println(创建解析器成功!);
//MyContentHandler是实现了ContentHandler接口的类
reader.setContentHandler(new MyContentHandler());
reader.setDTDHandler(new MyDTDHandler());
//对test.xml进行解析
reader.parse(test.xml);
System.out.println(解析完成!);
}catch(SAXException e){e.printStackTrace();}
}
}