我正在尝试使用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解析器不了解)解析器调用ContentHandler的C标签的startElement方法,然后调用C标签内的字符的字符方法。 DTD明确指出A标签只能有B标签作为子标签,而不是C标签,因为C首先需要嵌套在B内。 我不明白的是为什么解析器在意识到嵌套的C不在一个好地方之后调用了字符方法
我在ContentHandler方法中的应用程序逻辑依赖于根据DTD嵌套标签的假设,我不想用null-checker和错误处理代码填充这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;
}
}
感谢任何帮助!