Как правильно прочитать XML файл в 1С и избежать ошибок преобразования типов

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Работа с XML-файлами — это одна из наиболее часто встречающихся задач при организации обмена данными между 1С и сторонними системами (сайтами, государственными сервисами или другими базами данных). Несмотря на наличие мощных инструментов, таких как XDTO-фабрика, начинающие разработчики часто сталкиваются с неочевидным поведением платформы. В этой статье мы подробно разберем, как правильно читать XML, почему возникают ошибки при обработке одной строки и как сделать ваш код надежным.

Проблема: Список или Объект? Выясняем причину

Рассмотрим классическую ситуацию: вы пытаетесь прочитать XML-файл и заполнить таблицу документа. Вы используете ФабрикаXDTO.ПрочитатьXML(), и всё работает прекрасно, пока в файле несколько строк. Но как только во входящих данных остается ровно одна строка, код выдает ошибку. Проанализируем ситуацию: это происходит потому, что в объектной модели 1С, если схема (XSD) не задана жестко, один элемент превращается в ОбъектXDTO, а несколько элементов с одинаковым именем — в СписокXDTO. В результате цикл Для Каждого падает, так как он не может обойти одиночный объект как коллекцию.

Решение 1: Проверка типа через ТипЗнч()

Самый быстрый и простой способ решить проблему «одной строки» — добавить проверку типа перед обработкой данных. Разберем по шагам, как это реализовать в коде:


// Открываем файл для чтения
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);

// Читаем данные через фабрику
ДокументXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);

// Проверяем, что внутри свойства "Строка"
Если ТипЗнч(ДокументXDTO.Строка) = Тип("СписокXDTO") Тогда
    // Если это список (несколько строк), обходим в цикле
    Для Каждого ТекущаяСтрока Из ДокументXDTO.Строка Цикл
        ОбработатьСтрокуДанных(ТекущаяСтрока);
    КонецЦикла;
ИначеЕсли ТипЗнч(ДокументXDTO.Строка) = Тип("ОбъектXDTO") Тогда
    // Если это одиночный объект, обрабатываем его без цикла
    ОбработатьСтрокуДанных(ДокументXDTO.Строка);
КонецЕсли;

ЧтениеXML.Закрыть();

Этот метод надежен, но требует дублирования вызова логики обработки. Чтобы сделать код чище, рекомендуется выносить заполнение строки в отдельную процедуру или функцию.

Решение 2: Использование СериализаторXDTO для обмена между базами 1С

Если ваша задача — передать данные из одной базы 1С в другую, лучшим выбором будет СериализаторXDTO. Он автоматически преобразует объекты ссылочных типов, массивы и структуры в XML-формат, понятный платформе. Посмотрим на пример записи данных:


// Подготовка данных для записи
СписокДанных = Новый Массив;
Для Каждого Стр Из ТвояТаблица Цикл
    СтруктураСтроки = Новый Структура("КПП, Сумма", Стр.КПП, Стр.Сумма);
    СписокДанных.Добавить(СтруктураСтроки);
КонецЦикла;

// Запись в файл
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ПутьКФайлу);
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, СписокДанных);
ЗаписьXML.Закрыть();

При чтении такого файла через СериализаторXDTO.ПрочитатьXML(ЧтениеXML) 1С автоматически вернет массив структур, и вам не придется проверять, одна там строка или несколько. Однако помните: этот метод работает стабильно только тогда, когда структуры данных в обеих базах идентичны.

Решение 3: Последовательное чтение для больших файлов

Если XML-файл весит десятки или сотни мегабайт, методы ФабрикаXDTO и СериализаторXDTO могут привести к нехватке оперативной памяти, так как они загружают весь документ целиком. В таких случаях мы используем последовательное чтение. Проанализируем пример такого обхода:


ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);

Пока ЧтениеXML.Прочитать() Цикл
    // Ищем начало элемента "Строка"
    Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Строка" Тогда
        
        // Читаем атрибуты или переходим к содержимому
        КПП = ЧтениеXML.ЗначениеАтрибута("КПП");
        Сумма = ЧтениеXML.ЗначениеАтрибута("Сумма");
        
        // Добавляем строку в таблицу документа
        НоваяСтрока = ТаблицаДокумента.Добавить();
        НоваяСтрока.КПП = КПП;
        НоваяСтрока.Сумма = Число(Сумма);
        
    КонецЕсли;
КонецЦикла;

ЧтениеXML.Закрыть();

Этот метод работает максимально быстро и потребляет минимум ресурсов, но требует ручного разбора каждого тега и атрибута.

Типичные ошибки и как их избежать

  1. Несоответствие типов: При чтении из XML все данные изначально являются строками. Всегда используйте явное преобразование, например, Число(ЗначениеИзXML) или Дата(ЗначениеИзXML). Еще лучше использовать функцию XMLЗначение(Тип("Дата"), СтрокаИзXML), которая корректно обрабатывает стандарты XML.
  2. Пространства имен (Namespaces): Если в начале XML-файла указан атрибут xmlns, обычное чтение может вернуть пустые значения. В этом случае при использовании фабрики XDTO необходимо предварительно загрузить схему .xsd.
  3. Закрытие файлов: Всегда закрывайте объекты ЧтениеXML и ЗаписьXML методом Закрыть(). Если этого не сделать, файл может остаться заблокированным операционной системой до перезапуска сеанса 1С.

Важный совет: Если вы часто работаете с внешними XML-файлами сложной структуры, потратьте время на создание XSD-схемы. Подключив её к фабрике XDTO, вы навсегда забудете о проверках ТипЗнч(), так как 1С будет точно знать, где ожидается массив (список), а где — одиночное значение, даже если в конкретном файле данных мало.

Рассмотренные нами методы позволяют гибко подходить к задаче обмена данными. Для простых обменов между базами 1С выбирайте СериализаторXDTO, для интеграции со сторонними сервисами — ФабрикуXDTO с проверкой типов, а для высоконагруженных систем — последовательное чтение ЧтениеXML.

← На главную