4

我想离线使用 SAXReader ,问题是 SAXReader 正在根据 DTD 验证 xml。我不想更改 DTD 或 XML 中的任何其他内容。通过在本网站和其他来源上进行搜索,我发现了 2 个对我没有帮助的答案:

  1. 使用EntityResolver绕过网络调用
  2. 使用 setIncludeExternalDTDDeclarations(false)

我尝试做的示例:

protected Document getPlistDocument() throws MalformedURLException,
DocumentException {
    SAXReader saxReader = new SAXReader();
    saxReader.setIgnoreComments(false);
    saxReader.setIncludeExternalDTDDeclarations(false);
    saxReader.setIncludeInternalDTDDeclarations(true);
    saxReader.setEntityResolver(new MyResolver());
    Document plistDocument = saxReader.read(getDestinationFile().toURI().toURL());
    return plistDocument;
}

public class MyResolver implements EntityResolver {
    public InputSource resolveEntity (String publicId, String systemId)
    {
        if (systemId.equals("http://www.myhost.com/today")) {
            // if we want a custom implementation, return a special input source
            return null;

        } else {
            // use the default behaviour
            return null;
        }
    }
}

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">

我仍然无法离线工作,请建议...谢谢

堆栈跟踪:

14:20:44,358 ERROR [ApplicationBuilder] iphone build failed: Resource Manager - Problem handle Root.plist: www.apple.com Nested exception: www.apple.com
com.something.builder.sourcemanager.exception.SourceHandlingException: Resource Manager - Problem handle Root.plist: www.apple.com Nested exception: www.apple.com
****
****
Caused by: org.dom4j.DocumentException: www.apple.com Nested exception: www.apple.com
at org.dom4j.io.SAXReader.read(SAXReader.java:484)
at org.dom4j.io.SAXReader.read(SAXReader.java:291)  
... 10 more
4

3 回答 3

5

您的实体解析器不处理任何事情(因为它总是返回 null)。当系统 ID 为 时,让它返回一个 InputSource 到实际的 DTD 文件http://www.apple.com/DTDs/PropertyList-1.0.dtd,因为那是 dom4j 尝试下载的 DTD。

public class MyResolver implements EntityResolver {
    public InputSource resolveEntity (String publicId, String systemId)
    {
        if (systemId.equals("http://www.apple.com/DTDs/PropertyList-1.0.dtd")) {
            return new InputSource(MyResolver.class.getResourceAsStream("/dtds/PropertyList-1.0.dtd");
        } else {
            // use the default behaviour
            return null;
        }
    }
}

例如,此实现从类路径(在包中dtds)返回 DTD。您只需要自己下载 DTD 并将其捆绑到您的应用程序的 package 中dtds

于 2012-01-15T08:01:01.967 回答
0

还要注意,您实际上并没有针对 DTD 进行验证。为此,您需要执行以下操作:

SAXReader saxReader = new SAXReader(true);

否则 JB 是对的——他比我早了 3 分钟!

于 2012-01-15T08:23:44.497 回答
0

作为一个选项,如果您只想离线使用 SAXReader,请通过http://apache.org/xml/features/nonvalidating/load-external-dtdXerces 功能禁用其外部 DTD 获取。

根据Xerces features documentation,将此设置为false会使 SAXReader 完全忽略外部 DTD。

这个 SO 答案有一个代码示例。

于 2014-05-02T15:58:35.380 回答