как игнорировать ошибки XML при разборе ошибочного XML с помощью Sax (на Android) - PullRequest
4 голосов
/ 22 февраля 2012

Вопрос о синтаксическом анализаторе Sax XML на Android с использованием Java: мне нужно проанализировать XML-файлы, полученные из Интернета, и которые я не могу контролировать. Некоторые содержат ошибки и приводят к прерыванию работы синтаксического анализатора с ошибками типа «несоответствующий тег» или «неправильно сформированный (неверный токен)».

Эти ошибки не имеют для меня значения, я хочу их игнорировать и продолжать, я могу справиться с нарушенной структурой XML. Но я не могу исправить файлы XML, они не мои. Как я могу сказать Sax на Android (класс org.xml.sax.XMLReader) не генерировать исключение и продолжать работу? Присоединение ErrorHandler не сработало, и перехват исключения бесполезен, потому что я не могу возобновить разбор с того места, где он остановился.

Мой XML - это не HTML, но вот некоторые (X) примеры HTML, в которых браузеры игнорируют ошибки и продолжают работать. Я тоже хочу это сделать.

  • Браузеры работают с "
    " вместо "
    ", даже если тег никогда не закрывается.
  • " text " работает, даже если закрывающие теги расположены в неправильном порядке.
  • " коэффициент и конец " принят несмотря на недействительный токен, " коэффициент и конец " будет правильным.

Я бы предпочел не писать свой собственный анализатор, связанный с преобразованиями наборов символов и всем этим. Мне не нужно проверять XML. Вот мой код, сведенный к основам:

XMLReader r = SAXParserFactory.newInstance().newSAXParser().getXMLReader();
r.setErrorHandler(new MyLenientErrorHandlerThatNeverThrows());
r.setContentHandler(new MyImporterThatExtendsDefaultHandler());
r.parse(new InputSource(new BufferedReader(...)));

Спасибо!

1 Ответ

2 голосов
/ 02 марта 2012

Хорошо, похоже, это невозможно. Sax поддерживает обнаружение ошибок, но не восстановление ошибок, что делает его менее чем идеальным для надежного кода в этом примере. Получил это, заменив Sax XmlPullParser, который позволяет обернуть вызов следующего токена в блок try-catch:

try {
    XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
    XmlPullParser xpp = factory.newPullParser();
    xpp.setInput(in);
    int type = xpp.getEventType();
    while (type != XmlPullParser.END_DOCUMENT) {
        switch (type) {
          case XmlPullParser.START_TAG: startTag(xpp);             break;
          case XmlPullParser.END_TAG:   endTag(xpp);               break;
          case XmlPullParser.TEXT:      characters(xpp.getText()); break;
        }
        try {type = xpp.next();}
        catch (XmlPullParserException e) {}
    }
} catch (Exception e) {}
...