5

因此,我们的应用程序解析从 Web 服务(特别是PubMed)检索到的 XML 文档。这些文件声明了一个 DTD(一个示例)。默认情况下,与我天真的期望相反,我们使用的 XML 库(JDom2,我相信是基于 Xerces 构建的)在解析 XML 文档之前下载该 DTD。下载,如通过 Internet 向指定地址发出 HTTP 请求。

通过阅读此处的其他帖子,我的理解是阅读 DTD 是必要的,因为它可能包含解析 &foo; 所需的实体声明。文档中的位(顺便说一句,这在 XML 标准中很疯狂,对吧?)

我认为必须有一些简单、标准、任何人都知道他们在做什么的方式来指定我在本地拥有 DTD。但是,我所看到的只是提到设置 XML 目录(黑魔法)或创建自定义 EntityResolver(我的屁股)。

对于我遇到的其他问题,我在 Spring 或其他 Java 库中找到了一种克服它们的标准方法,而无需大量样板。然而,对于这个,我觉得我正在编写相对草率的脆弱代码来完成每个其他开发人员必须遇到的事情。

您如何使用众所周知的库编写 XML 应用程序,而不是一遍又一遍地发出 Web 请求来获取永不更改的文件?

PS:我发现这个问题是因为 PubMed 今天早些时候遇到了连接问题,并且当 XML 解析器无法检索 DTD 时,我的单元测试(使用基于真实查询的模拟文档)失败了。

PPS:当 W3C传播一个实际上乞求这种滥用的标准时,觉得这真的很有趣。

4

1 回答 1

2

我能想到的从不同源加载 DTD 的最佳方法是使用 EntityResolver,它不应该在后面那么痛苦。我使用 DOM4j 和 EntityResolver 加载本地 xml 资源,并将文件放在我的 jar 中,以便使用以下代码轻松访问。

new org.xml.sax.EntityResolver() 
{
    @Override
    public InputSource resolveEntity(String publicId, String systemId)
    {
        if (systemId != null && systemId.equals("http://something.com/xml.dtd"))
            return new InputSource(getClass().getResourceAsStream("../xml/local.dtd"));;
    }
};

我认为这是“标准”方式。

另一种方法可能是通过字符串修改 xml 文档替换 dtd 引用并注入任何可能使用的实体引用。

于 2012-12-15T12:09:55.050 回答