XML教程——采用SAX来解析XML
什么是 SAX
读取和操纵 XML 文件的标准方法是 DOM(“文档对象模型”)。遗憾的是,这种方法需要读取整个文件并将它存储到树结构中,因而效率不高、缓慢,并且会过度使用资源。
一种替代方法是使用 Simple API for XML 或 SAX。SAX 允许正在读取文档时处理该文档,这避免了在采取操作之前需要等待存储文档的所有内容。
SAX 是由 XML-DEV 邮件列表的成员开发的,Java 版本由 David Megginson 维护。他们的目的是提供一种更自然的方法来使用 XML,这种方法不会涉及到使用 DOM 的那种开销。
结果是基于事件的 API。解析器将事件(譬如,元素的开始或结束)发送给处理信息的事件处理程序。然后,应用程序自己可以处理数据。虽然原始文档保持不变,但 SAX 提供了操纵数据的方法,然后会将该方法导向另一个过程或文档。
对于 SAX,没有官方的标准;万维网(W3C)或其它官方组织不维护 SAX,但在 XML 社区中,它是一个事实上的标准。
回页首
SAX 处理是如何工作的
SAX 分析经过其的 XML 流,这非常象老式的自动收报机纸条。考虑以下 XML 代码片断:
<?xml version="1.0"?><samples><server>UNIX</server><monitor>color</monitor></samples>
?
一般情况下,SAX 处理器分析这段代码将生成以下事件:
Start documentStart element (samples)Characters (white space)Start element (server)Characters (UNIX)End element (server)Characters (white space)Start element (monitor)Characters (color)End element (monitor)Characters (white space)End element (samples)
?
SAX API 允许开发者捕获这些事件,并对它们进行操作。
SAX 处理涉及以下几步:
回页首
在SAX与DOM之间,如何选择
选择 DOM 还是 SAX,这取决于几个因素:
记住 SAX 和 DOM 不是互斥的,这一点很重要。可以使用 DOM 来创建事件的 SAX 流,可以使用 SAX 来创建 DOM 树。事实上,大多数解析器实际常常使用 SAX 来创建 DOM 树!
回页首
使用 JAXP 来创建解析器
接下来我们来看一下JAXP的SAX Parser是怎么样工作的。
首先声明 XMLReader xmlReader。然后使用 SAXParserFactory 来创建 SAXParser。正是 SAXParser 给您了 XMLReader。
import org.xml.sax.helpers.DefaultHandler;import javax.xml.parsers.SAXParser;import javax.xml.parsers.SAXParserFactory;import org.xml.sax.XMLReader;public class SurveyReader extends DefaultHandler{public SurveyReader() {}public static void main (String args[]) {XMLReader xmlReader = null;try {SAXParserFactory spfactory =SAXParserFactory.newInstance();spfactory.setValidating(false);//设置验证选项,如果您的XML文件是有效文档的话,就不用验证.这将提高处理速度SAXParser saxParser = spfactory.newSAXParser();xmlReader = saxParser.getXMLReader();} catch (Exception e) {System.err.println(e);System.exit(1);}}}
?
回页首
设置内容处理程序
一旦创建了解析器,则需要将 SurveyReader 设置为内容处理程序,以便于其接收事件。
xmlReader 的 setContentHandler() 方法完成这项工作。
...xmlReader = saxParser.getXMLReader();xmlReader.setContentHandler(new SurveyReader());} catch (Exception e) {...
?
当然,对于内容处理程序,这不是唯一的选项。
回页首
解析 InputSource
为了对文件进行实际地解析,需要 InputSource。这个 SAX 类封装了所有将要处理的数据,所以不必担心它来自哪里。
现在,准备对文件进行实际解析。应用程序将封装在 InputSource 中的文件传递给 parse(),然后应用程序会继续运行。
...import org.xml.sax.InputSource;...xmlReader = saxParser.getXMLReader();xmlReader.setContentHandler(new SurveyReader());InputSource source = new InputSource("surveys.xml");xmlReader.parse(source);} catch (Exception e) {...
?
可以编译和运行该程序,但这时应该什么也没有发生,因为应用程序还没有定义任何事件。
回页首
创建 ErrorHandler
当然总会有可能在试图进行解析时,数据有问题。在这样的情况下,有一个处理程序来处理错误和内容将是有帮助的。
就如同创建内容处理程序一样,可以创建出错处理程序。通常,将作为 ErrorHandler 的单独实例来创建它,但为了简化该示例,出错处理正是包含在 SurveyResults 中。由于该类继承了 DefaultHandler 且没有扩展 ContentHandler,所以这种双重用法是可能的。
需要关注的事件有三个:警告、错误和致命错误。
...import org.xml.sax.SAXParseException;public class SurveyReader extends DefaultHandler{public SurveyReader() {}public void error (SAXParseException e) {System.out.println("Error parsing the file: "+e.getMessage());}public void warning (SAXParseException e) {System.out.println("Problem parsing the file: "+e.getMessage());}public void fatalError (SAXParseException e) {System.out.println("Error parsing the file: "+e.getMessage());System.out.println("Cannot continue.");System.exit(1);}}....xmlReader.setContentHandler(new SurveyReader());xmlReader.setErrorHandler(new SurveyReader());//设置 ErrorHandlerInputSource source = new InputSource("surveys.xml");....public static void main (String args[]) {...
?
回页首
SAX 事件
以下事件是常用的;它们都在 org.xml.sax 包的 HandlerBase 类中定义。
还有更多的 SAX 事件:
?