java 使用相对路径上的 DTD 模式解析 XML 文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4726279/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 07:44:22  来源:igfitidea点击:

Parsing an XML file with a DTD schema on a relative path

javaxmldtd

提问by User1

I have the following java code:

我有以下java代码:


DocumentBuilder db=DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc=db.parse(new File("/opt/myfile"));

And /opt/myfilecontains something like:

/opt/myfile包含以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE archive SYSTEM "../../schema/xml/schema.dtd">
...

I get the following error:

我收到以下错误:

java.io.FileNotFoundException: /../schema/xml/schema.dtd (No such file or directory)

This is a large java framework that consumes an XML file produced elsewhere. I think the relative path is the problem. I don't think it will be acceptable to change the cwd before the JVM starts (the path comes from a config file that is read by the JVM itself) and I have not found a way to change the cwd while the JVM is running. How do I parse this XML file with the appropriate DTD?

这是一个大型 java 框架,它使用在别处生成的 XML 文件。我认为相对路径是问题所在。我认为在 JVM 启动之前更改 cwd 是不可接受的(路径来自 JVM 本身读取的配置文件),而且我还没有找到在 JVM 运行时更改 cwd 的方法。如何使用适当的 DTD 解析此 XML 文件?

回答by dogbane

You need to use a custom EntityResolverto tweak the path of the DTD so that it can be found. For example:

您需要使用自定义EntityResolver来调整 DTD 的路径,以便可以找到它。例如:

db.setEntityResolver(new EntityResolver() {
    @Override
    public InputSource resolveEntity(String publicId, String systemId)
            throws SAXException, IOException {
        if (systemId.contains("schema.dtd")) {
            return new InputSource(new FileReader("/path/to/schema.dtd"));
        } else {
            return null;
        }
    }
});

If schema.dtdis on your classpath, you can just use getResourceAsStreamto load it, without specifying the full path:

如果schema.dtd在您的类路径中,您可以使用getResourceAsStream加载它,而无需指定完整路径:

return new InputSource(Foo.class.getResourceAsStream("schema.dtd"));

回答by Roman

I used the custom EntityResolver like the example above but it still searched the DTD file in another base directory. So I debuged it and then found out I need to change user.dir system property. So I added this line to my application initialization method and it works now.

我像上面的例子一样使用了自定义的 EntityResolver,但它仍然在另一个基本目录中搜索 DTD 文件。所以我调试了它,然后发现我需要更改 user.dir 系统属性。所以我将这一行添加到我的应用程序初始化方法中,现在它可以工作了。

System.setProperty("user.dir")

回答by Shubham Jain

Below code work for me, It ignore DTD

下面的代码对我有用,它忽略了 DTD

Imports:

进口:

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

Code :

代码 :

File fileName = new File("XML File Path");
DocumentBuilderFactory documentBuilderFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder documentBuilder = documentBuilderFactory.newDocumentBuilder();
EntityResolver resolver = new EntityResolver () {
public InputSource resolveEntity (String publicId, String systemId) {
String empty = "";
ByteArrayInputStream bais = new ByteArrayInputStream(empty.getBytes());
                    System.out.println("resolveEntity:" + publicId + "|" + systemId);
                    return new InputSource(bais);
                    }
                    };
documentBuilder.setEntityResolver(resolver); 
Document document = documentBuilder.parse(fileName);