Работа с XML-файлами — это одна из наиболее часто встречающихся задач при организации обмена данными между 1С и сторонними системами (сайтами, государственными сервисами или другими базами данных). Несмотря на наличие мощных инструментов, таких как XDTO-фабрика, начинающие разработчики часто сталкиваются с неочевидным поведением платформы. В этой статье мы подробно разберем, как правильно читать XML, почему возникают ошибки при обработке одной строки и как сделать ваш код надежным.
Рассмотрим классическую ситуацию: вы пытаетесь прочитать XML-файл и заполнить таблицу документа. Вы используете ФабрикаXDTO.ПрочитатьXML(), и всё работает прекрасно, пока в файле несколько строк. Но как только во входящих данных остается ровно одна строка, код выдает ошибку. Проанализируем ситуацию: это происходит потому, что в объектной модели 1С, если схема (XSD) не задана жестко, один элемент превращается в ОбъектXDTO, а несколько элементов с одинаковым именем — в СписокXDTO. В результате цикл Для Каждого падает, так как он не может обойти одиночный объект как коллекцию.
Самый быстрый и простой способ решить проблему «одной строки» — добавить проверку типа перед обработкой данных. Разберем по шагам, как это реализовать в коде:
// Открываем файл для чтения
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
// Читаем данные через фабрику
ДокументXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
// Проверяем, что внутри свойства "Строка"
Если ТипЗнч(ДокументXDTO.Строка) = Тип("СписокXDTO") Тогда
// Если это список (несколько строк), обходим в цикле
Для Каждого ТекущаяСтрока Из ДокументXDTO.Строка Цикл
ОбработатьСтрокуДанных(ТекущаяСтрока);
КонецЦикла;
ИначеЕсли ТипЗнч(ДокументXDTO.Строка) = Тип("ОбъектXDTO") Тогда
// Если это одиночный объект, обрабатываем его без цикла
ОбработатьСтрокуДанных(ДокументXDTO.Строка);
КонецЕсли;
ЧтениеXML.Закрыть();
Этот метод надежен, но требует дублирования вызова логики обработки. Чтобы сделать код чище, рекомендуется выносить заполнение строки в отдельную процедуру или функцию.
Если ваша задача — передать данные из одной базы 1С в другую, лучшим выбором будет СериализаторXDTO. Он автоматически преобразует объекты ссылочных типов, массивы и структуры в XML-формат, понятный платформе. Посмотрим на пример записи данных:
// Подготовка данных для записи
СписокДанных = Новый Массив;
Для Каждого Стр Из ТвояТаблица Цикл
СтруктураСтроки = Новый Структура("КПП, Сумма", Стр.КПП, Стр.Сумма);
СписокДанных.Добавить(СтруктураСтроки);
КонецЦикла;
// Запись в файл
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл(ПутьКФайлу);
СериализаторXDTO.ЗаписатьXML(ЗаписьXML, СписокДанных);
ЗаписьXML.Закрыть();
При чтении такого файла через СериализаторXDTO.ПрочитатьXML(ЧтениеXML) 1С автоматически вернет массив структур, и вам не придется проверять, одна там строка или несколько. Однако помните: этот метод работает стабильно только тогда, когда структуры данных в обеих базах идентичны.
Если XML-файл весит десятки или сотни мегабайт, методы ФабрикаXDTO и СериализаторXDTO могут привести к нехватке оперативной памяти, так как они загружают весь документ целиком. В таких случаях мы используем последовательное чтение. Проанализируем пример такого обхода:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
Пока ЧтениеXML.Прочитать() Цикл
// Ищем начало элемента "Строка"
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Строка" Тогда
// Читаем атрибуты или переходим к содержимому
КПП = ЧтениеXML.ЗначениеАтрибута("КПП");
Сумма = ЧтениеXML.ЗначениеАтрибута("Сумма");
// Добавляем строку в таблицу документа
НоваяСтрока = ТаблицаДокумента.Добавить();
НоваяСтрока.КПП = КПП;
НоваяСтрока.Сумма = Число(Сумма);
КонецЕсли;
КонецЦикла;
ЧтениеXML.Закрыть();
Этот метод работает максимально быстро и потребляет минимум ресурсов, но требует ручного разбора каждого тега и атрибута.
Число(ЗначениеИзXML) или Дата(ЗначениеИзXML). Еще лучше использовать функцию XMLЗначение(Тип("Дата"), СтрокаИзXML), которая корректно обрабатывает стандарты XML.xmlns, обычное чтение может вернуть пустые значения. В этом случае при использовании фабрики XDTO необходимо предварительно загрузить схему .xsd.ЧтениеXML и ЗаписьXML методом Закрыть(). Если этого не сделать, файл может остаться заблокированным операционной системой до перезапуска сеанса 1С.Важный совет: Если вы часто работаете с внешними XML-файлами сложной структуры, потратьте время на создание XSD-схемы. Подключив её к фабрике XDTO, вы навсегда забудете о проверках ТипЗнч(), так как 1С будет точно знать, где ожидается массив (список), а где — одиночное значение, даже если в конкретном файле данных мало.
Рассмотренные нами методы позволяют гибко подходить к задаче обмена данными. Для простых обменов между базами 1С выбирайте СериализаторXDTO, для интеграции со сторонними сервисами — ФабрикуXDTO с проверкой типов, а для высоконагруженных систем — последовательное чтение ЧтениеXML.