处理词汇事件
原文: https://docs.oracle.com/javase/tutorial/jaxp/sax/events.html
此时,您已经消化了许多 XML 概念,包括 DTD 和外部实体。您还学习了 SAX 解析器的方法。本课程的其余部分将介绍只有在编写基于 SAX 的应用程序时才需要了解的高级主题。如果您的主要目标是编写基于 DOM 的应用程序,则可以跳到文档对象模型。
您之前看到,如果您以 XML 格式编写文本,则需要知道自己是否在 CDATA 部分。如果是,则尖括号(<)和&符号(&)应该不变地输出。但是如果你不在 CDATA 部分,它们应该被预定义的实体& lt;
和& amp;
。但是,您如何知道您是否正在处理 CDATA 部分?
然后,如果您以某种方式过滤 XML,则需要传递注释。通常,解析器会忽略注释。你怎么能得到评论,以便你能回应他们?
本节回答了这些问题。它向您展示了如何使用org.xml.sax.ext.LexicalHandler
来识别注释,CDATA 部分和对已解析实体的引用。
注释,CDATA 标记和对已解析实体的引用构成词汇信息 - 即涉及 XML 本身文本的信息,而不是 XML 的信息内容。当然,大多数应用程序仅关注 XML 文档的内容。此类应用程序不会使用LexicalEventListener
API。但是输出 XML 文本的应用程序会发现它非常宝贵。
注:词法事件处理是一个可选的解析器功能。解析器实现不需要支持它。 (参考实现会这样做。)本讨论假定您的解析器这样做。
LexicalHandler
如何工作
要在 SAX 解析器看到词法信息时得到通知,您可以使用LexicalHandler
配置作为解析器基础的XmlReader
。 LexicalHandler
接口定义了以下事件处理方法。
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
实例,并将其配置为将词法事件发送到词法处理器,如下所示。
// ...
SAXParser saxParser = factory.newSAXParser();
XMLReader xmlReader = saxParser.getXMLReader();
xmlReader.setProperty("http://xml.org/sax/properties/lexical-handler",
handler);
// ...
在这里,使用XMLReader
类中定义的setProperty()
方法配置XMLReader
。作为 SAX 标准的一部分定义的属性名称是 URN, http://xml.org/sax/properties/lexical-handler
。
最后,添加类似下面的代码来定义将实现接口的适当方法。
// ...
public void warning(SAXParseException err) {
// ...
}
public void comment(char[] ch, int start, int length) throws SAXException {
// ...
}
public void startCDATA() throws SAXException {
// ...
}
public void endCDATA() throws SAXException {
// ...
}
public void startEntity(String name) throws SAXException {
// ...
}
public void endEntity(String name) throws SAXException {
// ...
}
public void startDTD(String name, String publicId, String systemId)
throws SAXException {
// ...
}
public void endDTD() throws SAXException {
// ...
}
private void echoText() {
// ...
}
// ...
此代码将您的解析应用程序转换为词法处理器。剩下要做的就是给这些新方法中的每一个执行一个动作。