我有以下java代码:
DocumentBuilder db=DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc=db.parse(new File("/opt/myfile"));
/opt/myfile
包含类似的内容:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE archive SYSTEM "../../schema/xml/schema.dtd"> ...
我收到以下错误:
java.io.FileNotFoundException: /../schema/xml/schema.dtd (No such file or directory)
这是一个大型java框架,它使用其他地方生成的XML文件。我认为相对路径是问题所在。我不认为在JVM启动之前更改cwd是可以接受的(路径来自JVM本身读取的配置文件),并且我没有找到在JVM运行时更改cwd的方法。如何使用适当的DTD解析此XML文件?
答案 0 :(得分:18)
您需要使用自定义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;
}
}
});
如果您的类路径中有schema.dtd
,则可以使用getResourceAsStream
加载它,而不指定完整路径:
return new InputSource(Foo.class.getResourceAsStream("schema.dtd"));
答案 1 :(得分:0)
我使用了上面示例的自定义EntityResolver,但它仍在另一个基本目录中搜索DTD文件。所以我对其进行了调试,然后发现我需要更改user.dir系统属性。所以我将这一行添加到我的应用程序初始化方法中,现在可以正常工作。
System.setProperty("user.dir")
答案 2 :(得分:0)
下面的代码对我有用,它忽略了DTD
进口:
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;
代码:
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);