处理词汇事件

原文: https://docs.oracle.com/javase/tutorial/jaxp/sax/events.html

此时,您已经消化了许多 XML 概念,包括 DTD 和外部实体。您还学习了 SAX 解析器的方法。本课程的其余部分将介绍只有在编写基于 SAX 的应用程序时才需要了解的高级主题。如果您的主要目标是编写基于 DOM 的应用程序,则可以跳到文档对象模型

您之前看到,如果您以 XML 格式编写文本,则需要知道自己是否在 CDATA 部分。如果是,则尖括号(<)和&符号(&)应该不变地输出。但是如果你不在 CDATA 部分,它们应该被预定义的实体&amp; lt;&amp; amp; 。但是,您如何知道您是否正在处理 CDATA 部分?

然后,如果您以某种方式过滤 XML,则需要传递注释。通常,解析器会忽略注释。你怎么能得到评论,以便你能回应他们?

本节回答了这些问题。它向您展示了如何使用org.xml.sax.ext.LexicalHandler来识别注释,CDATA 部分和对已解析实体的引用。

注释,CDATA 标记和对已解析实体的引用构成词汇信息 - 即涉及 XML 本身文本的信息,而不是 XML 的信息内容。当然,大多数应用程序仅关注 XML 文档的内容。此类应用程序不会使用LexicalEventListener API。但是输出 XML 文本的应用程序会发现它非常宝贵。


:词法事件处理是一个可选的解析器功能。解析器实现不需要支持它。 (参考实现会这样做。)本讨论假定您的解析器这样做。


LexicalHandler如何工作

要在 SAX 解析器看到词法信息时得到通知,您可以使用LexicalHandler配置作为解析器基础的XmlReaderLexicalHandler接口定义了以下事件处理方法。

comment(String comment)

将评论传递给应用程序。

startCDATA(), endCDATA()

告诉 CDATA 部分何时开始和结束,告诉您的应用程序下次调用字符()时期望的字符类型。

startEntity(String name), endEntity(String name)

给出已解析实体的名称。

startDTD(String name, String publicId, String systemId), endDTD()

告知何时处理 DTD 并识别它。

要激活 Lexical Handler,您的应用程序必须扩展DefaultHandler并实现LexicalHandler接口。然后,您必须配置解析器委派给的XMLReader实例,并将其配置为将词法事件发送到词法处理器,如下所示。

  1. // ...
  2. SAXParser saxParser = factory.newSAXParser();
  3. XMLReader xmlReader = saxParser.getXMLReader();
  4. xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler",
  5. handler);
  6. // ...

在这里,使用XMLReader类中定义的setProperty()方法配置XMLReader 。作为 SAX 标准的一部分定义的属性名称是 URN, http://xml.org/sax/properties/lexical-handler

最后,添加类似下面的代码来定义将实现接口的适当方法。

  1. // ...
  2. public void warning(SAXParseException err) {
  3. // ...
  4. }
  5. public void comment(char[] ch, int start, int length) throws SAXException {
  6. // ...
  7. }
  8. public void startCDATA() throws SAXException {
  9. // ...
  10. }
  11. public void endCDATA() throws SAXException {
  12. // ...
  13. }
  14. public void startEntity(String name) throws SAXException {
  15. // ...
  16. }
  17. public void endEntity(String name) throws SAXException {
  18. // ...
  19. }
  20. public void startDTD(String name, String publicId, String systemId)
  21. throws SAXException {
  22. // ...
  23. }
  24. public void endDTD() throws SAXException {
  25. // ...
  26. }
  27. private void echoText() {
  28. // ...
  29. }
  30. // ...

此代码将您的解析应用程序转换为词法处理器。剩下要做的就是给这些新方法中的每一个执行一个动作。