在Java中解析xml时如何缓存dtd文件

时间:2018-06-26 21:30:41

标签: java xml xml-parsing dtd

我正在解析几百万个格式如下的xml文件:

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE test-document PUBLIC "-//TEST//TEST DOC//EN" "https://somerandomurl.com/test.dtd">
<test-document>...</test-document>

每次我解析一个文件时,都会下载相同的https://somerandomurl.com/test.dtd文件,这会占用大量带宽,而且似乎没有必要。有没有办法存储文件并使我的代码重定向我的本地副本?我无法编辑xml文件,因此它必须在我的代码中。给定以下Java代码,实现这种事情的合理方法是什么?

DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setIgnoringComments(true);
factory.setIgnoringElementContentWhitespace(true);
factory.setValidating(true);
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource("file.xml"));//My final document object.

2 个答案:

答案 0 :(得分:1)

如果您只想缓存下载的DTD文件,则可以使用XML目录。特别是,您将在解析规则中指定目录文件,例如以下

<catalog
  Xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
  <system
    systemId="https://somerandomurl.com/test.dtd"
    uri="file://mydir/test.dtd"/>
</catalog>

将具有系统标识符https://somerandomurl.com/test.dtd的实体解析为文件/mydir/test.dtd,该文件应包含通过https:URL链接的DTD文件的下载的本地副本。

链接

答案 1 :(得分:1)

首先将DTD读入字符串变量。

然后做

builder.setEntityResolver(
     (sysId, PubId) -> new InputSource(new StringReader(dtd)));

或者,如果您想更加小心,请在返回dtd的内容之前,让EntityResolver检查systemId和/或publicId是否符合预期。

请注意,这仍然涉及每次都解析DTD,只是节省了从网络获取DTD的成本。

也很重要:实例化XML解析器的开销很大(实例化DocumentBuilderFactory甚至更大)。确保重用工厂和解析器。