如何告诉xalan不要验证使用"document"函数检索的XML?

non*_*ont 6 java xml validation xalan

昨天甲骨文决定取消java.sun.com一段时间.这对我来说很麻烦,因为xalan试图验证一些XML但无法检索properties.dtd.

我正在使用xalan 2.7.1来运行一些XSL转换,我不希望它验证任何东西.所以尝试像这样加载XSL:

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setNamespaceAware(true);
spf.setValidating(false);
XMLReader rdr = spf.newSAXParser().getXMLReader();      
Source xsl = new SAXSource(rdr, new InputSource(xslFilePath));  
Templates cachedXSLT  = factory.newTemplates(xsl);
Transformer transformer = cachedXSLT.newTransformer();         
transformer.transform(xmlSource, result);  
Run Code Online (Sandbox Code Playgroud)

在XSL本身,我做这样的事情:

  <xsl:variable name="entry" select="document(concat($prefix, $locale_part, $suffix))/properties/entry[@key=$key]"/>
Run Code Online (Sandbox Code Playgroud)

此代码检索的XML在顶部具有以下定义:

<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<entry key="...
Run Code Online (Sandbox Code Playgroud)

尽管上面的java代码指示解析器不是VALIDATE,但它仍然向java.sun.com发送请求.虽然java.sun.com不可用,但这会使转换失败并显示以下消息:

 Can not load requested doc: http://java.sun.com/dtd/properties.dtd
Run Code Online (Sandbox Code Playgroud)

如何让xalan停止尝试验证从"document"函数加载的XML?

Car*_*icz 3

该文档提到,即使未验证,解析器也可以读取 DTD,因为可能需要使用 DTD 来解析(扩展)实体。

由于我无法控制 XML 文档,因此我无法选择修改 XML 的选项。

我设法通过破坏解析器来阻止提取 DTD 文档的尝试,如下所示。

我的代码使用 DocumentBuilder 返回 Document (= DOM),但根据 OP 示例的 XMLReader 也有一个方法,setEntityResolver因此相同的技术应该适用于该方法。

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setValidating(false); // turns off validation
factory.setSchema(null);      // turns off use of schema
                              // but that's *still* not enough!
builder = factory.newDocumentBuilder();
builder.setEntityResolver(new NullEntityResolver()); // swap in a dummy resolver
return builder().parse(xmlFile); 
Run Code Online (Sandbox Code Playgroud)

现在,这是我的假解析器:无论要求什么,它都会返回一个空的 InputStream。

/** my resolver that doesn't */
private static class NullEntityResolver implements EntityResolver {

    public InputSource resolveEntity(String publicId, String systemId) 
    throws SAXException, IOException {
        // Message only for debugging / if you care
        System.out.println("I'm asked to resolve: " + publicId + " / " + systemId);
        return new InputSource(new ByteArrayInputStream(new byte[0]));
    }

}
Run Code Online (Sandbox Code Playgroud)

或者,您的假解析器可能会返回作为本地资源或其他内容读取的实际文档流。