2009-07-26 2 views
10

Я хочу прочитать XML-файл, в котором есть объявление схемы.Как читать хорошо сформированный XML в Java, но пропустить схему?

И это все, что я хочу сделать, прочитал. Меня не волнует, действительно ли это, но я хочу, чтобы он был хорошо сформирован.

Проблема в том, что читатель пытается прочитать файл схемы и не удается.

Я не хочу, чтобы он даже пытался.

Я попытался отключить проверку, но он все еще настаивает на попытке прочитать файл схемы.

В идеале, я хотел бы сделать это с помощью запаса Java 5 JDK.

Вот то, что я до сих пор, очень просто:

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
    dbf.setValidating(false); 
    DocumentBuilder db = dbf.newDocumentBuilder(); 
    Document doc = db.parse(file); 

и вот исключение я получаю обратно:

java.lang.RuntimeException: java.io.IOException: Server returned HTTP response code: 503 for URL: http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd 

Да, это ПРОИСХОДИТ быть XHTML схемы, но это ISN 't проблема «XHTML», это проблема XML. Просто указывая, что так люди не отвлекаются. И в этом случае W3C в основном говорит: «Не просите об этом, это глупая идея», и я согласен. Но, опять же, это деталь вопроса, а не корень этого. Я не хочу просить об этом ВСЕ.

+0

похоже, что связано с: http://stackoverflow.com/questions/155101/make-documentbuilder-parse-ignore-dtd-references –

ответ

13

Ссылка не для схемы, но для DTD.

DTD-файлы могут содержать не только структурные правила. Они также могут содержать ссылки на сущности. Анализаторы XML обязаны загружать и анализировать ссылки DTD, поскольку они могут содержать ссылки на сущности, которые могут влиять на то, как анализируется документ, и содержимое файла (у вас может быть ссылка на сущность для символов или даже целые фразы текста).

Если вы хотите, чтобы избежать загрузки и разбора DTD с ссылкой, you can provide your own EntityResolver и протестировать DTD с ссылкой и решить, загружать ли локальную копию файла DTD или просто возвращать null.

Пример кода из ссылочного ответа на пользовательские EntityResolvers:

builder.setEntityResolver(new EntityResolver() { 
     @Override 
     public InputSource resolveEntity(String publicId, String systemId) 
       throws SAXException, IOException { 
      if (systemId.contains("foo.dtd")) { 
       return new InputSource(new StringReader("")); 
      } else { 
       return null; 
      } 
     } 
    }); 
+0

Я думал, что это то, что мне нужно было сделать, я просто создал «пустой» EntityResolver, который всегда возвращает пустой InputSource для everthing. Казалось, это трюк. –

+0

Я столкнулся с той же проблемой, и я применил это решение. Он решил исключение IOException. Меня беспокоит то, что DOCTYPE теряется с пустым револьвером. Я хочу, чтобы этот DOCTYPE сохранялся и не удалялся из ввода. Является ли это возможным. – Rachel

0

Я не проверял это, но вы можете попробовать позвонить setSchema на фабрике, пропуская нуль.

т.е.

DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); 
dbf.setValidating(false); 
dbf.setSchema(null); 
DocumentBuilder db = dbf.newDocumentBuilder(); 
Document doc = db.parse(file); 

Обновление: Глядя на DocumentBuilderImpl это выглядит как это может работать, из конструкторы он будет проверять грамматику с завода перед проверкой схемы.

От DocumentBuilderFactoryImpl:

public void setSchema(Schema grammar) { 
    this.grammar = grammar; 
} 

От DocumentBuilderImpl конструктора:

... 
this.grammar = dbf.getSchema(); 
if (grammar != null) { 
    XMLParserConfiguration config = domParser.getXMLParserConfiguration(); 
    XMLComponent validatorComponent = null; 
    /** For Xerces grammars, use built-in schema validator. **/ 
    ... 
} 
+0

Извините, похоже, не работает. – jpatokal

1

Вопрос здесь не один из проверки.Независимо от настроек проверки, анализатор все равно попытается разрешить любые ссылки в вашем документе, такие как сущности, DTD и (иногда) схемы. Только позже он решает проверить их использование (или нет). Вам нужно подключить средство распознавания сущности для «перехвата» этих попыток при де-ссылке.

Отъезд Apache XML Resolver для простого (иш) способа для этого.

9

Самый простой ответ это один лайнер, названный после создания DocumentBuilderFactory:

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

бесстыдно списаны из Make DocumentBuilder.parse ignore DTD references.

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