Как прочитать xml файл в указанной в нём кодировке на javascript

Есть клиентское приложение (НЕ node.js!), которое обрабатывает xml файлы. Юзер подгружает их на страницу, и дальше их надо парсить в браузере. Очень упрощенно код такой:

function openFile(event) {
   let input = event.target;
   let reader = new FileReader();
   reader.onload = function () {
     parse(reader.result);
   };
   reader.onerror = function () {
     console.log(reader.error);
   };
   reader.readAsText(input.files[0]);
}

function parse(text) {
   let parser = new DOMParser();
   let xml = parser.parseFromString(text, "text/xml");

   console.log(xml.xmlEncoding); //ок, но что дальше?

   for (let row of xml.getElementsByTagName("row")) {
       console.log(row.getAttribute("name"), row.firstChild.nodeValue);
   }
}
<input type="file" id="file" accept=".xml" onchange="openFile(event)">

Содержимое XML файла значения не имеет, для примера:

<?xml version="1.0" encoding="utf-8"?>
<data>
   <row name='имя'>значение</row>
</data>

Если файл в кодировке UTF-8, то все хорошо. Но он может быть, например, в кодировке windows-1251, тогда структура сохраняется, но внутри имя и значение будут знаками вопроса.

Если я вызову чтение с явным указанием кодировки, то все будет работать:

reader.readAsText(input.files[0], 'windows-1251');

Но проблема в том, что я не знаю, какая она изначально. Как быть?


Ответы (1 шт):

Автор решения: vsemozhebuty

Я, к сожалению, не знаю, какие тут есть традиции или отработанные алгоритмы, могу лишь предположить пару вариантов.

  1. Добавить в форму дополнительное поле с указанием кодировки.

  2. Читать файл как буфер при помощи FileReader.readAsArrayBuffer(). Передавать его в функцию парсинга. Там сначала попробовать декодировать его как UTF-8 при помощи TextDecoder. Если получилось прочитать кодировку и она не совпадает, перекодировать повторно тем же способом, но с указанной кодировкой. Но это может не сработать, если кодировка будет, например, UTF-16. Но тогда, возможно, DOMParser выдаст ошибку, её можно будет поймать и попробовать с многобайтовой кодировкой ещё раз.

  3. Поискать библиотеки, которые могут угадывать кодировку по части буфера ("npm guess encoding" в Гугле, например).

→ Ссылка