Разбор 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"));

Ответ 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);