Я использую стороннее приложение и хочу изменить один из его файлов. Файл хранится в XML, но с недопустимым типом документа.
Когда я пытаюсь прочитать, используйте ошибку, потому что тип документа содержит "file: ///ReportWiz.dtd" (как показано, в кавычках), и я получаю исключение из-за невозможности найти файл. Есть ли способ сказать разработчику документов, чтобы он игнорировал это? Я пробовал setValidate в false и setNamespaceAware в false для DocumentBuilderFactory.
Единственные решения, о которых я могу думать, это
DocumentBuilderFactory docFactory = DocumentBuilderFactory
.newInstance();
docFactory.setValidating(false);
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(file);



Моей первой мыслью было иметь дело с ним как с ручьем. Вы можете создать новый адаптер на каком-то уровне и просто скопировать ввод в вывод, за исключением оскорбительного текста.
Если файл короче (меньше половины гигабайта или около того), вы также можете прочитать все это в байтовый массив и внести в него изменения, а затем создать новый поток из байтового массива в свой построитель.
В этом преимущество удивительно громоздкого способа обработки потоков в Java: у вас действительно есть большая гибкость.
Похоже, что вы хотите создать подкласс FilterInputStream и перезаписать read (). Когда вызывается ваше чтение, вызовите super.read () для получения данных, отсканируйте и измените данные и верните их. Если у меня будет время, я подурачусь, но это не должно быть слишком сложно.
Вот пример с очень простой фильтрацией (я полагаю, он исключает непечатаемые символы из потока). cafeaulait.org/slides/sd2000west/javaio/44.html Ваш случай сложнее, потому что вам нужно распознать многосимвольный шаблон.
Еще одна вещь, которую я обсуждал, - это сохранение всего файла в строке, а затем выполнение моих манипуляций и подключение строки к файлу. Ни один из них не кажется простым или простым, но как лучше всего это сделать?
Обработка разрешения DTD вручную, либо путем возврата копии файла DTD (загруженного из пути к классам), либо путем возврата пустой. Вы можете сделать это, установив преобразователь сущностей в построителе документов:
EntityResolver er = new EntityResolver() {
@Override
public InputSource resolveEntity(String publicId, String systemId)
throws SAXException, IOException {
if ("file:///ReportWiz.dtd".equals(systemId)) {
System.out.println(systemId);
InputStream zeroData = new ByteArrayInputStream(new byte[0]);
return new InputSource(zeroData);
}
return null;
}
};
Более сложный, чем мне было нужно. Я не пробовал это делать, но на самом деле я просто искал способ полностью игнорировать это.
Скажите вашему DocumentBuilderFactory игнорировать объявление DTD следующим образом:
docFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
См. здесь для списка доступных функций.
Вам также может показаться, что работать с JDOM намного проще, чем с org.w3c.dom:
org.jdom.input.SAXBuilder builder = new SAXBuilder();
builder.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
org.jdom.Document doc = builder.build(file);
ТОЧНО то, что мне нужно. БЛАГОДАРНОСТЬ!! Добро пожаловать в SO.
если вы не хотите предполагать, что синтаксический анализатор - это xerces, и хотите общее решение, см. это
не могли бы вы помочь мне с примером кода (или ссылкой), это очень похоже на то, что я хочу сделать.