处理词汇事件

至此,您已经消化了许多 XML 概念,包括 DTD 和外部实体。您还了解了 SAX 解析器的使用方法。本类的其余部分涵盖了仅在编写基于 SAX 的应用程序时才需要理解的高级主题。如果您的主要目标是编写基于 DOM 的应用程序,则可以跳到文件对象模型

前面您已经看到,如果将文本写为 XML,则需要知道是否在 CDATA 部分中。如果是这样,则尖括号(<)和与号(&)应保持不变。但是,如果您不在 CDATA 部分中,则应将它们替换为 预定义的实体&lt;&amp;。但是如何知道您是否正在处理 CDATA 节?

再说一次,如果要以某种方式过滤 XML,则需要传递 注解。通常,解析器会忽略 注解。您如何获得 Comment,以便您可以回应它们?

本节回答这些问题。它显示了如何使用org\.xml\.sax\.ext\.LexicalHandler来标识 注解,CDATA 部分以及对已解析实体的引用。

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


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


LexicalHandler 的工作方式

要在 SAX 解析器看到词法信息时得到通知,请使用LexicalHandler配置位于解析器下面的XmlReaderLexicalHandlerinterface定义以下事件处理方法。

  • comment\(String comment\)

    • 将 注解 传递到应用程序。
  • startCDATA\(\) , endCDATA\(\)

    • 告诉 CDATA 节何时开始和结束,告诉您的应用程序下次调用characters\(\)时需要什么样的字符。
  • startEntity\(String name\) , endEntity\(String name\)

    • 给出已解析实体的名称。
  • startDTD\(String name, String publicId, String systemId\) , endDTD\(\)

    • 告知何时处理 DTD 并进行标识。

要激活词法处理程序,您的应用程序必须扩展DefaultHandler并实现LexicalHandlerinterface。然后,您必须配置解析器委托给的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() {
    // ...
}

// ...

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