Игнорирование DTD при разборе XML - PullRequest
10 голосов
/ 10 ноября 2011

Как можно игнорировать объявление DTD при разборе файла с библиотекой XOM xml. Мой файл имеет следующую строку:

<?xml version="1.0"?>
<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN" "NCBI_BlastOutput.dtd">
//rest of stuff here 

И когда я пытаюсь построить () мой документ, я получаю исключение filenotfound для файла DTD. Я знаю, что у меня нет этого файла, и мне все равно, как его удалить при использовании XOM?

Вот фрагмент кода:

public BlastXMLParser(String filePath) {
    Builder b = new Builder(false);
     //not a good idea to have exception-throwing code in constructor
    try {

        _document = b.build(filePath);
    } catch (ParsingException ex) {
        Logger.getLogger(BlastXMLParser.class.getName()).log(Level.SEVERE,"err", ex);
    } catch (IOException ex) {
        //
    }

private Elements getBlastReads() {
    Element root = _document.getRootElement();
    Elements rootChildren = root.getChildElements();

    for (int i = 0; i < rootChildren.size(); i++) {
        Element child = rootChildren.get(i);
        if (child.getLocalName().equals("BlastOutput_iterations")) {

            return child.getChildElements();
        }
    }

    return null;
}
}

Я получаю исключение NullPointerException в этой строке:

Element root = _document.getRootElement();

После удаления строки DTD из исходного XML-файла я могу успешно проанализировать ее, но это не вариант в конечной производственной системе.

Ответы [ 2 ]

14 голосов
/ 10 ноября 2011

Предпочтительным решением будет реализация EntityResolver , который перехватывает запросы на DTD и перенаправляет их во встроенную копию.Если у вас

  1. нет доступа к DTD и
  2. абсолютно уверены, что вам это не понадобится (кроме проверки, он также может объявлять символьные объекты, которые используются вдокумент) и
  3. вы используете реализацию Xerces XML Parser

, вы можете отключить выборку DTD, установив соответствующую функцию SAX.В XOM это должно быть возможно путем передачи XMLReader в конструктор Builder следующим образом:

import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;

...

XMLReader xmlreader = XMLReaderFactory.createXMLReader();
xmlreader.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
Builder builder = new Builder(xmlreader);
0 голосов
/ 10 ноября 2011

Согласно их документации, это способ анализа документа без какой-либо проверки.

try {
  Builder parser = new Builder();
  Document doc = parser.build("http://www.cafeconleche.org/");
}
catch (ParsingException ex) {
  System.err.println("Cafe con Leche is malformed today. How embarrassing!");
}
catch (IOException ex) {
  System.err.println("Could not connect to Cafe con Leche. The site may be down.");
}

Если вы хотите проверить схему XML, вам нужно позвонить new Builder(true):

try {
  Builder parser = new Builder(true);
  Document doc = parser.build("http://www.cafeconleche.org/");
}
catch (ValidityException ex) {
  System.err.println("Cafe con Leche is invalid today. (Somewhat embarrassing.)");
}
catch (ParsingException ex) {
  System.err.println("Cafe con Leche is malformed today. (How embarrassing!)");
}
catch (IOException ex) {
  System.err.println("Could not connect to Cafe con Leche. The site may be down.");
}

Обратите внимание, что теперь может быть выдано еще одно исключение: ValidityException

...