XML认证教程,第 8 部分: SAX Parser

来源:百度文库 编辑:神马文学网 时间:2024/04/29 22:00:32
读取和操纵 XML 文件的标准方法是 DOM(“文档对象模型”)。遗憾的是,这种方法需要读取整个文件并将它存储到树结构中,因而效率不高、缓慢,并且会过度使用资源。
读取和操纵 XML 文件的标准方法是 DOM(“文档对象模型”)。遗憾的是,这种方法需要读取整个文件并将它存储到树结构中,因而效率不高、缓慢,并且会过度使用资源。
一种替代方法是使用 Simple API for XML 或 SAX。SAX 允许正在读取文档时处理该文档,这避免了在采取操作之前需要等待存储文档的所有内容。
SAX 是由 XML-DEV 邮件列表的成员开发的,Java 版本由 David Megginson 维护。他们的目的是提供一种更自然的方法来使用 XML,这种方法不会涉及到使用 DOM 的那种开销。
结果是基于事件的 API。解析器将事件(譬如,元素的开始或结束)发送给处理信息的事件处理程序。然后,应用程序自己可以处理数据。虽然原始文档保持不变,但 SAX 提供了操纵数据的方法,然后会将该方法导向另一个过程或文档。
对于 SAX,没有官方的标准;万维网(W3C)或其它官方组织不维护 SAX,但在 XML 社区中,它是一个事实上的标准。
SAX 分析经过其的 XML 流,这非常象老式的自动收报机纸条。考虑以下 XML 代码片断:
UNIXcolor
一般情况下,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 还是 SAX,这取决于几个因素:
应用程序的目的:如果必须对数据进行更改,并且作为 XML 将它输出,则在大多数情况下,使用 DOM。与使用 XSL 转换来完成的简单结构更改不一样,如果是对数据本身进行更改,则尤其应该使用 DOM。 数据的数量:对于大文件,SAX 是更好的选择。 将如何使用数据:如果实际上只使用一小部分数据,则使用 SAX 将数据抽取到应用程序中,这种方法更好些。另一方面,如果知道将需要向后引用已经处理过的信息,则 SAX 可能不是正确的选择。 需要速度:通常,SAX 实现比 DOM 实现快。
记住 SAX 和 DOM 不是互斥的,这一点很重要。可以使用 DOM 来创建事件的 SAX 流,可以使用 SAX 来创建 DOM 树。事实上,大多数解析器实际常常使用 SAX 来创建 DOM 树!
接下来我们来看一下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。这个 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 的单独实例来创建它,但为了简化该示例,出错处理正是包含在 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[]) {...
以下事件是常用的;它们都在 org.xml.sax 包的 HandlerBase 类中定义。
startDocument 表示文档开始。 endDocument 表示文档结束。 startElement 表示元素开始。当一对标记中的起始标记中的所有内容被处理后,解析器 激发此事件。包括了标记名和其属性。 endElement 表示元素结束。 characters 包含字符数据,类似于 DOM 的一个 Text 节点。
还有更多的 SAX 事件:
ignorableWhitespace 此事件类似于我们前面所讨论的无用 DOM 节点。它与 character 事件的区别,好处是:如果您不需要空格符,您可以通过忽略这个事件来忽略所有的空格符。 warning、error 和 fatalError 这三个事件表示了解析错误。您可根据需要来响应它们。 setDocumentLocator 这个事件允许您存储一个 SAX 的 Locator 对象。Locator 对象可以用来找出在文档中确切发生事件的地方。