如何在Java中读取格式良好的XML,但是跳过架构?

Wil*_*ung 13 java xml

我想读取一个包含模式声明的XML文件.

这就是我想做的一切,请阅读.我不在乎它是否有效,但我希望它形成良好.

问题是读者正在尝试读取模式文件,并且失败了.

我甚至不想尝试.

我已经尝试禁用验证,但它仍然坚持尝试读取模式文件.

理想情况下,我想用库存Java 5 JDK来做这件事.

这是我到目前为止所做的,非常简单:

    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    dbf.setValidating(false);
    DocumentBuilder db = dbf.newDocumentBuilder();
    Document doc = db.parse(file);
Run Code Online (Sandbox Code Playgroud)

这是我回来的例外:

java.lang.RuntimeException: java.io.IOException: Server returned HTTP response code: 503 for URL: http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd
Run Code Online (Sandbox Code Playgroud)

是的,这个HAPPENS是一个XHTML模式,但这不是一个"XHTML"问题,它是一个XML问题.只是指出这一点,所以人们不会分心.并且,在这种情况下,W3C基本上是在说"不要求这个东西,这是一个愚蠢的想法",我同意.但是,这又是问题的细节,而不是问题的根源.我不想要求它.

Mad*_*sen 14

引用不是针对Schema,而是针对DTD.

DTD文件不仅包含结构规则.它们还可以包含实体引用.XML解析器有义务加载和解析DTD引用,因为它们可能包含可能影响文档解析方式的实体引用和文件内容(您可以为字符甚至整个文本短语提供实体引用).

如果您想要避免加载和解析引用的DTD,您可以提供自己的EntityResolver并测试引用的DTD,并决定是加载DTD文件的本地副本还是仅返回null.

自定义EntityResolvers上引用答案的代码示例:

   builder.setEntityResolver(new EntityResolver() {
        @Override
        public InputSource resolveEntity(String publicId, String systemId)
                throws SAXException, IOException {
            if (systemId.contains("foo.dtd")) {
                return new InputSource(new StringReader(""));
            } else {
                return null;
            }
        }
    });
Run Code Online (Sandbox Code Playgroud)


jpa*_*kal 10

最简单的答案是这个单行程序,在创建DocumentBuilderFactory后调用:

dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
Run Code Online (Sandbox Code Playgroud)

Make DocumentBuilder.parse无耻地抄袭忽略DTD引用.