Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/xml/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何告诉xalan不要验证使用;文件「;功能?_Java_Xml_Validation_Xalan - Fatal编程技术网

Java 如何告诉xalan不要验证使用;文件「;功能?

Java 如何告诉xalan不要验证使用;文件「;功能?,java,xml,validation,xalan,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

昨天,甲骨文决定关闭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);  
  <xsl:variable name="entry" select="document(concat($prefix, $locale_part, $suffix))/properties/entry[@key=$key]"/>
在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);  
  <xsl:variable name="entry" select="document(concat($prefix, $locale_part, $suffix))/properties/entry[@key=$key]"/>

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

请注意,如果DTD定义了XML文件所依赖的任何实体,则禁用DTD加载将导致解析失败。也就是说,要禁用DTD加载,请尝试以下方法,它假定您使用的是Java附带的默认Xerces

    /*
     * Instantiate the SAXParser and set the features to prevent loading of an external DTD
     */
   SAXParser sp = SAXParserFactory.newInstance().newSAXParser();
   XMLReader xrdr = sp.getXMLReader();
   xrdr.setFeature("http://xml.org/sax/features/validation", false);
   xrdr.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
如果您确实需要DTD,那么另一种选择是实现本地XML目录

    /*
     * Instantiate the SAXParser and add catalog support
     */
   SAXParser sp = SAXParserFactory.newInstance().newSAXParser();
   XMLReader xrdr = sp.getXMLReader();

   CatalogResolver cr = new CatalogResolver();
   xrdr.setEntityResolver(cr);
您必须为其提供适当的DTD和XML目录定义。这对我们很有帮助


CatalogResolver查看系统属性
xml.catalog.files
以确定要加载的目录。

尝试在
SAXParserFactory
上使用setFeature

试试这个:

SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setValidating(false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
我认为这应该足够了,否则请尝试设置其他一些功能:

spf.setFeature("http://xml.org/sax/features/validation", false);
spf.setFeature("http://xml.org/sax/features/external-general-entities", false);
spf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar", false);

我只是将doctype声明从XML中剥离出来,因为其他方法都不起作用。当我开始讨论它时,我会尝试这样做:

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

由于我无法控制XML文档,因此无法使用

我通过破坏解析器成功地阻止了拉入DTD文档的尝试,如下所示

我的代码使用DocumentBuilder返回一个文档(=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); 
现在,这里是我的假解析器:它返回一个空的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]));
    }

}


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

很抱歉发布,但我找到了一个实际可行的解决方案,并决定共享它

1. 由于某些原因,setValidating(false)不起作用。在某些情况下,它仍然下载外部DTD文件。为了防止出现这种情况,您应该按照建议附加一个自定义EntityResolver:

将为每个外部实体请求调用EntityResolver。返回null将不起作用,因为在此之后框架仍将从Internet下载文件。相反,您可以返回一个有效DTD的空流,建议如下:

2. 您正在告诉读取XSLT代码的SAX解析器setValidating(false)。也就是说,它不会验证XSLT。当它遇到document()函数时,它会使用另一个解析器加载链接的XML文件,该解析器仍会验证该文件,并下载外部实体。要处理此问题,您应该将自定义URIResolver附加到转换器:

Transformer transformer = cachedXSLT.newTransformer();
transformer.setURIResolver(new MyCustomURIResolver());
当转换器遇到document()函数时,它将调用您的URIResolver实现。您的实现必须为传递的URI返回一个源。最简单的方法是按照建议返回StreamSource。但是在您的情况下,您应该自己解析文档,使用您已有的自定义SAXParser(或每次创建一个新的)防止验证和外部请求


因此,您必须在代码中实现两个自定义接口。

哦,顺便说一句,并不是Xalan试图在这里加载DTD,而是Xerces。这在Xalan获得输入流之前很久就已经发生了。谢谢你的回答。我尝试了您在上面推荐的功能设置,但在尝试下载DTD时仍然失败!您是使用Xerces进行解析,还是安装了另一个XML解析器?执行XSL时是否继承了解析器的设置?因为document函数是在XSL本身被解析很久之后执行的。是的,我使用xerces进行解析。至少我认为我是。tomcat的lib dir中有一个xercesImpl.jar,当我逐步阅读代码时,SAXParserFactory被实例化为org.apache.xerces.jaxp.saxparserfactorympl。所以我很有信心Xerces是有效的。只是尝试了一下,没有运气!我开始怀疑解析器设置是否适用于我们解析的XSL,而不是XSL使用document函数读取的文档?
private class MyCustomEntityResolver implements EntityResolver {
    public InputSource resolveEntity(String publicId, String systemId) {
        return new InputSource(new StringReader(""));
    }
}
Transformer transformer = cachedXSLT.newTransformer();
transformer.setURIResolver(new MyCustomURIResolver());
private class MyCustomURIResolver implements URIResolver {
    public Source resolve(String href, String base) {
        return new SAXSource(rdr,new InputSource(href));
    }
}