我正在使用第三方应用程序,并希望更改其中一个文件。该文件存储在XML中,但文档类型无效。
当我尝试阅读时使用它会出错,因为doctype包含“file:///ReportWiz.dtd” (如图所示,带引号),我得到一个无法找到文件的例外。有没有办法告诉docbuilder忽略这个?对于DocumentBuilderFactory,我已经尝试将setValidate设置为false并将setNamespaceAware设置为false。
我能想到的唯一解决方案是
DocumentBuilderFactory docFactory = DocumentBuilderFactory .newInstance(); docFactory.setValidating(false); DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); Document doc = docBuilder.parse(file);
答案 0 :(得分:4)
告诉你的DocumentBuilderFactory忽略这样的DTD声明:
docFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
有关可用功能的列表,请参阅here。
您还可能会发现JDOM比org.w3c.dom更容易使用:
org.jdom.input.SAXBuilder builder = new SAXBuilder();
builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
org.jdom.Document doc = builder.build(file);
答案 1 :(得分:2)
通过返回DTD文件的副本(从类路径加载)或返回空副本来手动处理DTD的解析。您可以通过在文档构建器上设置实体解析程序来执行此操作:
EntityResolver er = new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
if ("file:///ReportWiz.dtd".equals(systemId)) {
System.out.println(systemId);
InputStream zeroData = new ByteArrayInputStream(new byte[0]);
return new InputSource(zeroData);
}
return null;
}
};
答案 2 :(得分:1)
我的第一个想法是将其作为流处理。您可以在某个级别创建一个新的适配器,只需将输入复制到输出,除了有问题的文本。
如果文件很短(大约一半左右),您还可以将整个内容读入一个字节数组并在那里进行修改,然后从字节数组中创建一个新的流到您的构建器中。
这是Java处理流的惊人笨重方式的优势,实际上你有很大的灵活性。
答案 3 :(得分:0)
我讨论的另一件事是将所有文件存储在一个字符串中,然后进行操作并将String连接到一个文件。这些文件中没有一个看起来干净或容易,但是最好的方法是什么?< / p>
答案 4 :(得分:0)
如果您不想假设解析器是xerces,并且想要通用解决方案,请参阅this