在SAX解析器中处理具有依赖关系的私有外部DTD

时间:2015-04-28 18:47:16

标签: java xml tomcat dtd saxparser

我尝试使用DOCTYPE中指定的私有外部DTD解析XML文件,如下所示:

<!DOCTYPE MY1 SYSTEM "my1.dtd">

要在本地处理此DTD以进行验证,我为EntityResolver指定了XMLReader parser

        //use local DTD
        parser.setEntityResolver(new EntityResolver() {
            @Override
            public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
                if (systemId.contains(my1Dtd)) {
                    return new InputSource(MyClass.class.getResourceAsStream(MY1_DTD_RESOURCE_PATH));
                } else {
                    return null;
                }
            }
        });

InputSource正确返回,但是存在与DTD相关的问题:在DTD内部有对另一个DTD的引用。所以我将所有DTD放在同一个包中。但是当我在Tomcat FileNotFoundException D:\apache-tomcat-6.0.29\bin\my2.dtd (The system cannot find the file specified)上部署的应用程序被抛出时。

我的问题是:我们如何正确指定此依赖关系?是应该用resolveEntity方法构建还是我在路径中犯了一个错误(my2.dtd<!ENTITY % MY2 SYSTEM "my2.dtd">内声明为my1.dtd并存储在同一个包中。

1 个答案:

答案 0 :(得分:0)

当解析器需要加载my2.dtd文件时,也应该调用resolveEntity

因此,你需要以类似的方式修改它:

 public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException {
            if (systemId.contains(my1Dtd)) {
                return new InputSource(MyClass.class.getResourceAsStream(MY1_DTD_RESOURCE_PATH));
            } else if (systemId.contains(my2Dtd)) {
                return new InputSource(MyClass.class.getResourceAsStream(MY2_DTD_RESOURCE_PATH));
            } else {
                return null;
            }
        }

但是,为避免此类工作,您应该考虑使用解析器,例如the Apache resolver。此解析器依赖于OASIS entity resolution / XML catalogs,它允许您创建XML格式的目录,由解析程序读取,这样您每次有新DTD或将其移动到其他位置时都不需要修改代码管他呢。 (此解析程序包与Apache Xerces发行版捆绑在一起,如果它已经是您正在使用的解析器)。