Как разрешить парсер SAX определять кодировку из объявления xml?
Я пытаюсь разобрать xml файлы из разных источников (над которыми у меня мало контроля). Большинство из них закодированы в UTF-8 и не вызывают никаких проблем, используя следующий фрагмент:
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
FeedHandler handler = new FeedHandler();
InputSource is = new InputSource(getInputStream());
parser.parse(is, handler);
Так как SAX по умолчанию соответствует UTF-8, это нормально. Однако некоторые из документов заявляют:
<?xml version="1.0" encoding="ISO-8859-1"?>
Несмотря на то, что ISO-8859-1 объявлен SAX, по умолчанию все еще используется UTF-8.
Только если я добавлю:
is.setEncoding("ISO-8859-1");
Будет ли SAX использовать правильную кодировку.
Как я могу позволить SAX автоматически определять правильную кодировку из объявления xml без специальной настройки? Мне нужно это, потому что я не знаю перед тем, что будет кодировать файл.
Спасибо заранее,
Allan
Ответы
Ответ 1
Используйте InputStream в качестве аргумента InputSource, если вы хотите, чтобы Sax автоматически определял кодировку.
Если вы хотите установить конкретную кодировку, используйте Reader с указанной кодировкой или setEncoding.
Почему? Поскольку алгоритмы кодирования автоопределения требуют необработанных данных, а не преобразуются в символы.
Вопрос в теме: Как разрешить синтаксический анализатор SAX определять кодировку из объявления xml? Я обнаружил, что Аллан ответил на вопрос обманчивым, и я представил альтернативный вариант, основанный на комментарии Йорна Хорстмана и моем более позднем опыте.
Ответ 2
Я сам нашел ответ.
Анализатор SAX использует InputSource внутри и из документов InputSource:
Анализатор SAX будет использовать Объект InputSource для определения того, как читать XML-ввод. Если есть поток символов доступен, синтаксический анализатор будет читать этот поток напрямую, без всякой текстовой кодировки объявление найдено в этом потоке. Если нет потока символов, но есть поток байтов, синтаксический анализатор будет использовать этот поток байтов, используя кодирование, указанное в InputSource или иначе (если не указано кодирование) автоопределение кодировки символов используя такой алгоритм, как спецификации XML. Если ни один поток символов или байтовый поток доступный, парсер будет пытаться открыть URI-соединение с ресурсом идентифицированный системным идентификатором.
Итак, в основном вам нужно передать поток символов в синтаксический анализатор для его получения правильной кодировки. См. Решение ниже:
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
FeedHandler handler = new FeedHandler();
Reader isr = new InputStreamReader(getInputStream());
InputSource is = new InputSource();
is.setCharacterStream(isr);
parser.parse(is, handler);