При интеграции 1С с внешними системами разработчики часто сталкиваются с ситуацией, когда входящие XML-файлы сформированы в кодировке windows-1251 или значения из файла считываются как пустые. Разберем по шагам, как правильно открывать такие файлы платформой 1С:Предприятие 8.3, а также выясним частые причины, почему методы обхода XML не возвращают ожидаемых данных.
Для чтения XML-файлов в платформе 1С предусмотрен встроенный объект ЧтениеXML. Метод ОткрытьФайл позволяет явно задать кодировку, если это необходимо.
Рассмотрим синтаксис метода ОткрытьФайл:
ОткрытьФайл(<ИмяФайлаXML>, <Параметры>, <НаборСхемXML>, <Кодировка>)
Четвертый параметр метода принимает строку с названием кодировки. Посмотрим на пример вызова метода с явным указанием windows-1251:
ТекстXML = Новый ЧтениеXML;
ТекстXML.ОткрытьФайл("C:\data\import.xml", , , "windows-1251");
Важный нюанс: спецификация XML предполагает, что кодировка документа указывается в заголовочной строке XML-файла (например, <?xml version="1.0" encoding="windows-1251"?>). Встроенный синтаксический анализатор 1С автоматически считывает эту декларацию. Если кодировка внутри файла указана корректно, парсер применит её автоматически даже без передачи четвертого параметра.
Одной из главных причин, почему при обходе XML не удается получить данные, является путаница между атрибутами узла и текстовыми узлами (значениями элементов).
Проанализируем структуру XML-файла:
<!-- Пример 1: Текстовый узел (элемент со значением) -->
<Sell_to_Customer_No_>SATURN</Sell_to_Customer_No_>
<!-- Пример 2: Элемент с атрибутом -->
<Sell_to_Customer_No_ code="SATURN" />
В первом примере текст SATURN не является атрибутом тега <Sell_to_Customer_No_>. Это значение отдельного подчиненного узла с типом ТипУзлаXML.Текст. Поэтому вызов метода КоличествоАтрибутов() для тега <Sell_to_Customer_No_> вернет 0, а метод ПолучитьАтрибут() вернет значение Неопределено.
Чтобы корректно считать значение текстового элемента, необходимо последовательно перемещаться по узлам документа с помощью метода Прочитать() и проверять свойство ТипУзла.
Разберем рабочий пример последовательного обхода XML-структуры:
ТекстXML = Новый ЧтениеXML;
ТекстXML.ОткрытьФайл(ИмяФайла, , , "windows-1251");
Пока ТекстXML.Прочитать() Цикл
// Проверяем начало элемента
Если ТекстXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
ИмяЭлемента = ТекстXML.Имя;
// Если у элемента есть атрибуты, обрабатываем их отдельно
Если ТекстXML.КоличествоАтрибутов() > 0 Тогда
Пока ТекстXML.ПрочитатьАтрибут() Цикл
ИмяАтрибута = ТекстXML.Имя;
ЗначениеАтрибута = ТекстXML.Значение;
КонецЦикла;
КонецЕсли;
// Проверяем текстовое содержимое (значение внутри тега)
ИначеЕсли ТекстXML.ТипУзла = ТипУзлаXML.Текст Тогда
ЗначениеЭлемента = ТекстXML.Значение;
// Здесь выполняем обработку полученного значения
КонецЕсли;
КонецЦикла;
ТекстXML.Закрыть();
Если файл содержит некорректную заголовочную декларацию или поврежденные символы, напрямую открыть его через ЧтениеXML может не получиться. В таких случаях применяют предварительную загрузку в строку.
Сначала файл считывается объектным типом ЧтениеТекста с принудительной кодировкой windows-1251, после чего полученная строка передается в парсер через метод УстановитьСтроку().
ТекстФайла = Новый ЧтениеТекста("C:\data\import.xml", "windows-1251");
СтрокаXML = ТекстФайла.Прочитать();
ТекстФайла.Закрыть();
ТекстXML = Новый ЧтениеXML;
ТекстXML.УстановитьСтроку(СтрокаXML);
// Далее выполняем стандартный обход узлов
Файл загружается как бинарные данные и конвертируется в юникод-строку 1С методом ПолучитьСтрокуИзДвоичныхДанных(), указав исходную кодировку "windows-1251".
Благодаря правильной проверке типов узлов ТипУзлаXML.НачалоЭлемента и ТипУзлаXML.Текст, вы сможете корректно выгружать данные любой сложности независимо от того, представлены они атрибутами тегов или вложенными текстовыми значениями.