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

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

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

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

我甚至不想尝试。

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

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

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

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(file); 

这是我回来的例外:

 java.lang.RuntimeException: java.io.IOException: Server returned HTTP response code: 503 for URL: http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd 

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

引用不是针对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; } } }); 

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

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

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

这里的问题不是validation问题。 无论validation设置如何,解析器仍将尝试解析文档中的任何引用,例如实体,DTD和(有时)模式。 它只是在它之后决定使用它们(或不是)进行validation。 您需要插入实体解析器以“拦截”这些取消引用的尝试。

查看Apache XML Resolver以获得一种简单(ish)的方法。

我没有测试过这个,但你可以尝试在工厂调用setSchema传递null。

 DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); dbf.setValidating(false); dbf.setSchema(null); DocumentBuilder db = dbf.newDocumentBuilder(); Document doc = db.parse(file); 

更新:看看DocumentBuilderImpl看起来这可能有用,从构造函数开始,它会在检查模式之前检查工厂的语法。

来自DocumentBuilderFactoryImpl:

 public void setSchema(Schema grammar) { this.grammar = grammar; } 

从DocumentBuilderImpl构造函数:

 ... this.grammar = dbf.getSchema(); if (grammar != null) { XMLParserConfiguration config = domParser.getXMLParserConfiguration(); XMLComponent validatorComponent = null; /** For Xerces grammars, use built-in schema validator. **/ ... }