使用Xerces-J的SAX方式进行XML程序设计
--SAX2(Simple API for XML)的结构
在本文中,笔者将首先介绍SAX Version 2 的使用方法,在以后介绍DOM Level 2 的使用方法。
SAX接口解析XML文件的基本原理为:首先获得一个实现了SAX接口的解析器,这个解析器通常是由第三方软件公司提供的;然后自己写一个符合SAX标准的处理器类,并且把这个类注册到刚刚做好的解析器;解析XML文件;解析器会把XML文件作为一个文件流读出来,然后再把文件流转换成一个事件流,这个事件流中的内容包括“文档开始”、“文档结束”、“元素开始”、“元素结束”等等标志文件状态的事件;根据事件调用注册到解析器里的处理器里面的相应的方法;在解析器进行XML文件的解析的同时,应用程序可以调用解析器提供的方法,对解析器的行为进行控制或获取解析器的状态。
SAX1发布于1998年五月,已经成为XML应用的世界标准,ibm/apache,sun,oracle,microsoft等知名大公司都要相应的解析器提供。SAX2接口是在2000年发布的,目前最高版本是SAX2release2pre。Ibm/apache已经有成熟的产品提供,microsoft的MSXML3.0 解析器也已经正式支持SAX2。sun的解析器目前已经处于预发布状态,oracle的XML解析器对SAX2的支持目前处于Beta状况。SAX2继承了SAX1的所有功能,仍然采用事件流/调用流的构架,但是SAX2同SAX1最大的几个区别在于:
在了解进一步的知识之前,首先我们需要了解的是,SAX不是一个XML的解析器,而是提供了一个通用的接口,这个接口使各种XML的解析器可以相互转换。这些支持SAX解析器具有相同的方法,并且可以通过Java的系统设置进行配置。
SAX2的基本构架最重要的组成部分是接口org.xml.sax.XMLReader和类org.xml.sax.helpers.DefaultHandler。在SAX2的架构里XMLReader取代了SAX1构架中的XMLParser,进行实际的XML文件的解析工作。类DefaultHandler实现了org.xml.sax.EntityResolver,org.xml.sax.DTDHandler,org.xml.sax.ContentHandler,org.xml.sax.ErrorHandler这四个接口,通过继承这个类,我们可以实现解析XML文件的所有任务。
下面的表1介绍了XMLReader中的主要方法及使用方法。表2介绍了另外一个很重要的接口DefaultHandler。
方法 | 使用说明 |
ContentHandler getContentHandler() | 返回当前的内容处理器。 |
DTDHandler getDTDHandler() | 返回当前的DTD处理器。 |
EntityResolver getEntityResolver() | 返回当前的实体解析器。 |
ErrorHandler getErrorHandler() | 返回当前的错误处理器。 |
boolean getFeature(java.lang.String name) | 返回解析器的指定特性。参数为特性的名字,返回值为boolean值。关于特性的使用我们会在后面专门介绍。 |
Object getProperty(java.lang.String name) | 返回解析器的指定属性。参数为属性的名字,这个字符串是可以自己创建的。关于属性的使用我们会在后面专门介绍。 |
void parse(InputSource input) | 通过调用这个方法,应用程序可以通知解析器开始解析,参数为XML文件的来源。 |
void parse(java.lang.String systemId) | 通过调用这个方法,应用程序可以通知解析器开始解析,参数为XML文件的来源。 |
void setContentHandler(ContentHandler handler) | 设置内容处理器。 |
void setDTDHandler(DTDHandler handler) | 设置DTD处理器。 |
void setEntityResolver(EntityResolver resolver) | 设置实体解析器。 |
void setErrorHandler(ErrorHandler handler) | 设置错误处理器。 |
void setFeature(java.lang.String name, boolean value) | 设置特性。第一个参数为特性的名字,第二个参数为特性的值。 |
void setProperty(java.lang.String name, java.lang.Object value) | 设置属性。第一个参数为属性的名字,第二个参数为属性的值。 |
方法 | 使用说明 |
public void characters(char[] ch, int start, int length) | 当XML文档中出现字符串数据的时候这个方法被调用。第一个参数是包含字符串数据的字符数组,第二个参数是起始位置,第三个参数是长度。需要注意的是解析器可能把在一对tag内包含的字符串分成几个部分,连续调用charData方法若干次。 |
void endDocument() | 当XML文档结束的时候这个方法被调用,这个方法每处理一个XML文档仅仅会被调用一次。 |
void endElement(java.lang.String uri, java.lang.String localName, java.lang.String qName) | 当解析器在XML文件流中遇到一个Element的时候调用这个方法。第一个参数是名空间的URI,若没有则是一个空字符串;第二个参数是名空间的局域名,若没有则是一个空字符串,第三个参数为tag的名字。 |
void endPrefixMapping(String prefix) | 当解析器遇到名空间映射结束的相应的tag的时候会调用这个方法。 |
void error(SAXParseException e) | 处理一个可以修正的错误。 |
void fatalError(SAXParseException e) | 处理一个不可修正的错误。 |
void ignorableWhitespace(char[] ch, int start, int length) | 当解析器在XML文件流中遇到可以忽略的空白的时候会调用这个方法,注意,非校验的XML解析器也有可能调用这个方法。 |
void notationDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId) | 当解析器在XML文件流中遇到符号声明的时候调用这个方法,第一个参数为名称,第二个是publicId,第三个是systemId。 |
void processingInstruction( java.lang.String target, java.lang.String data) | 当解析器在XML文件流中遇到处理指令的时候这个方法被调用。典型的处理指令如<?xml-stylesheet type="text/xml" href="14-2.xsl"?>。其中xml-stylesheet为第一个参数即target的内容,type="text/xml" href="14-2.xsl"为第二个参数即data中的内容。 |
void setDocumentLocator(Locator locator) | 为解析器设置一个Locator,以便获取行号,列号等信息。 |
InputSource resolveEntity(java.lang.String publicId, java.lang.String systemId) | 解析器在打开一个外部的实体,例如DTD文件之前会调用这个方法,给应用程序开发者一个机会来修改其URI。如果返回null那么解析器将会按照原来的URI打开外部实体。 |
void skippedEntity(java.lang.String name) | 解析器在XML文件流中发现不认识的实体时会调用这个方法。由于无校验解析不打开外部的DTD文件,这种情况通常在无校验解析地情况下遇到。 |
void startDocument() | 文档开始时调用这个方法。 |
void startPrefixMapping(java.lang.String prefix, java.lang.String uri) | 当解析器遇到名空间映射的时候会调用这个方法,注意,这个方法同对应的endPrefixMapping不一定成对调用。 |
void unparsedEntityDecl(java.lang.String name, java.lang.String publicId, java.lang.String systemId, java.lang.String notationName) | 当解析器遇到一个无法解析的实体声明的时候调用这个方法。 |
void warning(SAXParseException e) | 当解析器遇到一个应该警告的状态时调用这个方法。 |
另外一个非常重要的类是org.xml.sax.helpers.XMLReaderFactory,这个类提供了创建一个XMLReader的方法。这个类只有两个方法,如表3。
方法 | 使用说明 |
static XMLReader createXMLReader() | 这个方法从系统属性org.xml.sax.driver中读取数据,然后建立一个XMLReader的实例。例如 java –Dorg.xml.sax.driver=org.apache.xerces.parsers.SAXParser xxx xxx.xml 将会动态地建立一个org.apache.xerces.parsers.SAXParser的实例作为XMLReader。 |
static XMLReader createXMLReader(java.lang.String className) | 用一个解析器类名字的字符串作为参数建立一个XMLReader的实例。 |
Xerces-J中的SAX接口的使用方法和我们曾经介绍的?LFRED的使用方法比较类似,Xerces-J的SAXParser是一个实现了XmlParser界面的类,在使用时我们首先需要设置相应的Handler,然后调用parse方法,这时Xerces-J会把XML文件当作一个流,从里面按照顺序把字符一个一个读出来,在遇到XML文件中的元素的时候会调用在解析文件前设置的Handler类中相应的Handler函数,对XML文件的内容要在Handler方法中进行处理。