Java更改并移动非标准XML文件

时间:2008-12-10 23:57:41

标签: java xml dom parsing

我正在使用第三方应用程序,并希望更改其中一个文件。该文件存储在XML中,但文档类型无效。

当我尝试阅读时使用它会出错,因为doctype包含“file:///ReportWiz.dtd” (如图所示,带引号),我得到一个无法找到文件的例外。有没有办法告诉docbuilder忽略这个?对于DocumentBuilderFactory,我已经尝试将setValidate设置为false并将setNamespaceAware设置为false。

我能想到的唯一解决方案是

  • 逐行将文件复制到一个新文件中,省略违规行,做我需要做的事情,然后复制到另一个新文件并插入有问题的行,或者
  • 上面做的大致相同但是使用某种类型的FileStream(虽然我不知道如何做到这一点......帮助?)
DocumentBuilderFactory docFactory = DocumentBuilderFactory
                    .newInstance();
docFactory.setValidating(false);
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(file);

5 个答案:

答案 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