Java:如何防止EntityResolver中的'systemId'#resolveEntity(String publicId,String systemId)从绝对化到当前工作目录

时间:2009-10-30 06:18:12

标签: java xml-parsing entityresolver

我想解析以下XML文档以解析其中的所有实体:

 <!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),将实体解析器设置为MyEntityResolver(即setEntityResolver(new MyEntityResolver())),但systemId中的MyEntityResolver#resolveEntity(String publicId, String systemId)始终被绝对化为当前的工作目录。

我也尝试过调用setFeature("http://xml.org/sax/features/resolve-dtd-uris", false);,但这没有任何帮助。

那么我怎样才能达到我的目的呢?

谢谢!

2 个答案:

答案 0 :(得分:8)

显然,还有另一个名为EntityResolver2的界面,它是旧EntityResolver的扩展名。 (谈论令人困惑的名字!)

无论如何,我发现EntityResolver2实现了我想要的,也就是说,它不会对systemId进行任何更改,因此它将始终完全符合XML文档中指定的内容。 / p>

答案 1 :(得分:0)

来自the EntityResolver Javadocs

  

如果系统标识符是URL,则   SAX解析器必须完全解析它   在报告之前   应用

此外,org.xml.sax docs还有关于resolve-dtd-uris功能的说法:

  

不适用于   EntityResolver.resolveEntity(),其中   不用于报告声明...

我认为你要么将你的base-URI设置为你可以使用的东西,要么使用公共ID而不是系统ID。