Разбор XML файла с помощью схемы DTD на относительном пути
У меня есть следующий код 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 файл, созданный в другом месте. Я думаю, что относительный путь - проблема. Я не думаю, что будет приемлемым изменение cwd до запуска JVM (путь происходит из файла конфигурации, который считывается самой JVM), и я не нашел способ изменить cwd во время работы JVM. Как проанализировать этот XML файл с соответствующим DTD?
Ответы
Ответ 1
Для настройки пути DTD вам нужно использовать EntityResolver, чтобы его можно было найти. Например:
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"));
Ответ 2
Вы также можете полностью игнорировать DTD:http://marcels-javanotes.blogspot.com/2005/11/parsing-xml-file-without-having-access.html
Ответ 3
Я использовал пользовательский EntityResolver, как пример выше, но он все еще искал DTD файл в другом базовом каталоге. Поэтому я отладил его, а затем выяснил, что мне нужно изменить свойство system.dir. Поэтому я добавил эту строку в мой метод инициализации приложения и теперь работает.
System.setProperty("user.dir")
Ответ 4
Ниже код работает для меня, он игнорирует 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);