处理词汇事件
至此,您已经消化了许多 XML 概念,包括 DTD 和外部实体。您还了解了 SAX 解析器的使用方法。本类的其余部分涵盖了仅在编写基于 SAX 的应用程序时才需要理解的高级主题。如果您的主要目标是编写基于 DOM 的应用程序,则可以跳到文件对象模型。
前面您已经看到,如果将文本写为 XML,则需要知道是否在 CDATA 部分中。如果是这样,则尖括号(<)和与号(&)应保持不变。但是,如果您不在 CDATA 部分中,则应将它们替换为 预定义的实体<
和&
。但是如何知道您是否正在处理 CDATA 节?
再说一次,如果要以某种方式过滤 XML,则需要传递 注解。通常,解析器会忽略 注解。您如何获得 Comment,以便您可以回应它们?
本节回答这些问题。它显示了如何使用org\.xml\.sax\.ext\.LexicalHandler
来标识 注解,CDATA 部分以及对已解析实体的引用。
注解,CDATA 标记和对已解析实体的引用构成词法信息,即与 XML 本身的文本有关的信息,而不是与 XML 的信息内容有关的信息。当然,大多数应用程序仅与 XML 文档的内容有关。此类应用程序将不使用LexicalEventListener
API。但是输出 XML 文本的应用程序会发现它非常宝贵。
注意- 词法事件处理是可选的解析器功能。不需要解析器实现来支持它。 (参考实现是这样做的.)本讨论假定您的解析器这样做。
LexicalHandler 的工作方式
要在 SAX 解析器看到词法信息时得到通知,请使用LexicalHandler
配置位于解析器下面的XmlReader
。 LexicalHandler
interface定义以下事件处理方法。
-
comment\(String comment\)
- 将 注解 传递到应用程序。
-
startCDATA\(\)
,endCDATA\(\)
- 告诉 CDATA 节何时开始和结束,告诉您的应用程序下次调用
characters\(\)
时需要什么样的字符。
- 告诉 CDATA 节何时开始和结束,告诉您的应用程序下次调用
-
startEntity\(String name\)
,endEntity\(String name\)
- 给出已解析实体的名称。
-
startDTD\(String name, String publicId, String systemId\)
,endDTD\(\)
- 告知何时处理 DTD 并进行标识。
要激活词法处理程序,您的应用程序必须扩展DefaultHandler
并实现LexicalHandler
interface。然后,您必须配置解析器委托给的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
。
最后,添加类似以下代码的内容,以定义将实现interface的适当方法。
// ...
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() {
// ...
}
// ...
这段代码会将您的解析应用程序转换为词汇处理程序。剩下要做的就是给每个新方法执行一个动作。