在java项目中使用自定义dtd文件,并且在xml文件中引用dtd文件使用的是相对路径,需要注意的问题
dtd文件和对应的xml文件
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE users SYSTEM "image.dtd"> <users> <user> <id>1</id> <name>jerry</name> <url></url> </user> <user> <id>2</id> <name>tom</name> <url></url> </user> <user> <id>3</id> <name>tel</name> <url></url> </user> </users>
<?xml version="1.0" encoding="UTF-8"?> <!ELEMENT users (user*)> <!ELEMENT user (id,name,url)> <!ELEMENT id (#PCDATA)> <!ELEMENT name (#PCDATA)> <!ELEMENT url (#PCDATA)>
java代码
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); InputStream is = MyXMLTest.class.getClassLoader().getResourceAsStream("image.xml"); Document root = builder.parse(is);
此时通过builder.parse(inputstream), 如果使用的是public 来定位dtd文件 ,没有什么问题
但是引入的dtd文件是相对路径,运行时
java.io.FileNotFoundException: D:\workspace\workspace_study4editon3\p2p\image.dtd (系统找不到指定的文件。)
java系统就没办法定位到该dtd文件xml处理器知道如何定位带有公共标识符的dtd,就不需要url了
而如果使用的是相对url("上面的image.dtd"),那么必须给解析器一个file对象或者url对象,而不能是输入流.如果必须是个 输入流 就需要指定一个resolverEntity接口的实现 为该解析器
相对路径 时的解决办法
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); URL url= MyXMLTest.class.getClassLoader().getSystemResource("image.xml"); Document document = builder.parse(url.toString());
或者
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); DocumentBuilder builder = factory.newDocumentBuilder(); builder.setEntityResolver(new EntityResolver() { @Override public InputSource resolveEntity(String publicId, String systemId) throws SAXException, IOException { return new InputSource(MyXMLTest.class.getClassLoader().getResourceAsStream("image.dtd")); } }); InputStream is = MyXMLTest.class.getClassLoader().getResourceAsStream("image.xml"); Document root = builder.parse(is);