Изменение Java и перемещение нестандартного XML-файла

Я использую стороннее приложение и хочу изменить один из его файлов. Файл хранится в XML, но с недопустимым типом документа.

Когда я пытаюсь прочитать, используйте ошибку, потому что тип документа содержит "file: ///ReportWiz.dtd" (как показано, в кавычках), и я получаю исключение из-за невозможности найти файл. Есть ли способ сказать разработчику документов, чтобы он игнорировал это? Я пробовал setValidate в false и setNamespaceAware в false для DocumentBuilderFactory.

Единственные решения, о которых я могу думать, это

  • копировать файл построчно в новый файл, опуская строку с нарушением, делая то, что мне нужно сделать, затем копировать в другой новый файл и вставлять обратно строку с нарушением, или
  • делаю в основном то же самое, но работаю с каким-то FileStream (хотя я не понимаю, как я могу это сделать ... помочь?)
DocumentBuilderFactory docFactory = DocumentBuilderFactory
                    .newInstance();
docFactory.setValidating(false);
DocumentBuilder docBuilder = docFactory.newDocumentBuilder();
Document doc = docBuilder.parse(file);
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
2
0
1 414
5
Перейти к ответу Данный вопрос помечен как решенный

Ответы 5

Моей первой мыслью было иметь дело с ним как с ручьем. Вы можете создать новый адаптер на каком-то уровне и просто скопировать ввод в вывод, за исключением оскорбительного текста.

Если файл короче (меньше половины гигабайта или около того), вы также можете прочитать все это в байтовый массив и внести в него изменения, а затем создать новый поток из байтового массива в свой построитель.

В этом преимущество удивительно громоздкого способа обработки потоков в Java: у вас действительно есть большая гибкость.

не могли бы вы помочь мне с примером кода (или ссылкой), это очень похоже на то, что я хочу сделать.

Adam Lerman 11.12.2008 03:09

Похоже, что вы хотите создать подкласс FilterInputStream и перезаписать read (). Когда вызывается ваше чтение, вызовите super.read () для получения данных, отсканируйте и измените данные и верните их. Если у меня будет время, я подурачусь, но это не должно быть слишком сложно.

Bill K 12.12.2008 01:19

Вот пример с очень простой фильтрацией (я полагаю, он исключает непечатаемые символы из потока). cafeaulait.org/slides/sd2000west/javaio/44.html Ваш случай сложнее, потому что вам нужно распознать многосимвольный шаблон.

Bill K 12.12.2008 01:21

Еще одна вещь, которую я обсуждал, - это сохранение всего файла в строке, а затем выполнение моих манипуляций и подключение строки к файлу. Ни один из них не кажется простым или простым, но как лучше всего это сделать?

Обработка разрешения 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;
        }
    };

Более сложный, чем мне было нужно. Я не пробовал это делать, но на самом деле я просто искал способ полностью игнорировать это.

Adam Lerman 11.12.2008 03:46
Ответ принят как подходящий

Скажите вашему 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.

Adam Lerman 11.12.2008 03:46

если вы не хотите предполагать, что синтаксический анализатор - это xerces, и хотите общее решение, см. это

Другие вопросы по теме