的Java:如何防止“的systenId”中的EntityResolver#resolveEntity(字符串publicId,字符串的systenId)被绝对化到当前工作目录

问题描述:

我想解析以下XML文件来解决它的所有实体:的Java:如何防止“的systenId”中的EntityResolver#resolveEntity(字符串publicId,字符串的systenId)被绝对化到当前工作目录

<!DOCTYPE doc SYSTEM 'mydoc.dtd'> 
<doc>&title;</doc> 

我的EntityResolver应该取得与从数据库中给定系统ID的外部实体,然后进行解析,请参阅下面的说明:

private static class MyEntityResolver 
{ 
    public InputSource resolveEntity(String publicId, String systemId) 
     throws SAXException, IOException 
    { 
     // At this point, systemId is always absolutized to the current working directory, 
     // even though the XML document specified it as relative. 
     // E.g. "file:///H:/mydoc.dtd" instead of just "mydoc.dtd" 
     // Why??? How can I prevent this??? 

     SgmlEntity entity = findEntityFromDatabase(systemId); 
     InputSource is = new InputSource(new ByteArrayInputStream(entity.getContents())); 
     is.setPublicId(publicId); 
     is.setSystemId(systemId); 
     return is; 
    } 
} 

我尝试都使用DOM(的DocumentBuilder)和SAX(XMLReader的) ,将实体解析器设置为MyEnt ityResolver(即setEntityResolver(new MyEntityResolver())),但systemIdMyEntityResolver#resolveEntity(String publicId, String systemId)总是被absolutized到当前工作目录。

我也试过打电话setFeature("http://xml.org/sax/features/resolve-dtd-uris", false);,但那并没有什么帮助。

那么我该如何实现我想要的?

谢谢!

显然,还有另外一个接口叫做EntityResolver2,它是旧的EntityResolver的扩展。 (谈论混淆的名字!)

无论如何,我发现EntityResolver2达到我想要的东西,也就是说,它不会做任何更改systemId,所以它永远究竟是什么在XML文档中指定。

the EntityResolver Javadocs

如果系统标识符是一个URL,该 SAX解析器必须将其报告给 应用程序之前完全 解决它。

此外,org.xml.sax docs有这样说的决心,DTD的URI的功能:

它并不适用于 EntityResolver.resolveEntity(),它 不用于报告的声明。 ..

我认为你必须设置你的base-URI为你可以使用的东西,或者使用public-id而不是system-id。