2008-12-10 8 views
2

Я использую стороннее приложение и хотел бы изменить один из его файлов. Файл хранится в XML, но с недопустимым типом doctype.Изменение Java и перемещение нестандартного XML-файла

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

Единственное решение, я могу думать, являются

  • копия файла построчно в новый файл, минуя обижая линию, делать то, что мне нужно делать, а затем скопировать в другой новый файл и вставить обижая линия обратно, или
  • делают в основном те же выше, но работая с FileStream какой-то (хотя я не ясно, о том, как я мог бы сделать this..help?)
DocumentBuilderFactory docFactory = DocumentBuilderFactory 
        .newInstance(); 
docFactory.setValidating(false); 
DocumentBuilder docBuilder = docFactory.newDocumentBuilder(); 
Document doc = docBuilder.parse(file);

ответ

4

Сообщите DocumentBuilderFactory игнорировать декларацию DTD, как это:

docFactory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false); 

См here для списка доступных функций.

Вы также можете найти 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); 
1

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

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

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

+0

не могли бы вы помочь мне с некоторым примером кода (или ссылкой), это звучит так же, как то, что я хочу делать. – 2008-12-11 00:09:34

+0

Похоже, что вы хотите сделать, это подкласс FilterInputStream и перезаписать read(). Когда вы будете читать, вызовите super.read(), чтобы получить данные, просмотреть и изменить данные и вернуть их. Я буду обманывать его, если я получу какое-то время, но это не должно быть слишком сложно. – 2008-12-11 22:19:48

+0

Вот пример, который имеет очень простую фильтрацию (это исключает непечатаемые символы из потока, который я считаю). http://www.cafeaulait.org/slides/sd2000west/javaio/44.html Ваш случай сложнее, потому что вам нужно распознать многосимвольный шаблон. – 2008-12-11 22:21:51

0

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

2

Ручное разрешение 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; 
     } 
    }; 
0

, если вы не хотите взять на себя парсер Xerces, и вы хотите увидеть общее решение this

Смежные вопросы