2

我正在尝试使用 Apache Xerces SAX2 验证解析器解析和验证一个非常简单的 XML 文件。DTD 是从 XML 文件中引用的,我的简单实体解析器可以成功返回 DTD 文件的正确 InputStream。我有一个非常基本的标签结构,它与命名它们无关,所以我只是给 XML 标签一个字母。主标签是A,A标签内可能有零个或多个B,但只有B。B里面有零个或多个C。所以一个合适的 XML 应该是:

<A>
<B><C>somecharacters</C></B>
</A>

我创建了一些单元测试并经历了一个奇怪的行为。我想如果我给上面的解析器一个类似的 XML,但是只有 C 的结束标记没有匹配的开始标记并且没有父元素 B,解析器将报告 DTD 验证错误。下面是根据 DTD 故意设计的无效 XML 示例:

<A>
<C>somecharacters</C></B>
</A>

很明显,这个 XML 片段的格式不正确。不幸的是(或者我不理解 SAX 解析器的某些内容)解析器为 C 标记调用 ContentHandler 的 startElement 方法,然后为 C 标记内的字符调用 characters 方法。DTD 明确指出,A 标签只能有 B 标签作为子标签,而不是 C,因为 C 首先需要嵌套在 B 中。我不明白的是为什么解析器在意识到嵌套的 C 不在一个好地方后调用 characters 方法

我在 ContentHandler 方法中的应用程序逻辑依赖于标签根据 DTD 嵌套的假设,我不想用空检查器和错误处理代码填充这 3 个方法,因为我认为这是 DTD 验证器的工作。

我设置解析器的代码是(异常处理部分不相关):

    private static final String VALIDATION_FEATURE = "http://xml.org/sax/features/validation";
    private static final String SAX_PARSER_IMPLEMENTATION = "org.apache.xerces.parsers.SAXParser";
    ......
    XMLReader parser = XMLReaderFactory.createXMLReader(SAX_PARSER_IMPLEMENTATION);
    parser.setFeature(VALIDATION_FEATURE, true);
    parser.setErrorHandler(new CustomErrorHandler());
    parser.setEntityResolver(entityResolver);
    parser.setContentHandler(handler);

    InputSource inputSource = new InputSource(stream);
    try {
        parser.parse(inputSource);
    } catch (IOException e) {
        throw new ControlFileReadException("Error while parsing the control file.", e);
    } catch (SAXException e) {
        if (e.getCause() instanceof IncorrectCounterNameException) {
            throw new IncorrectCounterNameException(e.getCause());
        } else {
            throw e;
        }
    }

    private final class CustomErrorHandler implements ErrorHandler {
    public void warning(SAXParseException spe) throws SAXException {
        throw spe;
    }

    public void fatalError(SAXParseException spe) throws SAXException {
        throw spe;
    }

    public void error(SAXParseException spe) throws SAXException {
        throw spe;
    }
}

任何帮助表示赞赏!

4

0 回答 0