XML в 1С 8.3 на практике: от разбора файла до обмена между базами
Содержание
Работа с XML в 1С строится на трёх объектах встроенного языка: ЧтениеXML читает файл потоком, ЗаписьXML формирует файл обмена, а ПостроительDOM загружает документ целиком, когда нужен произвольный доступ к узлам. Для обмена данными между конфигурациями поверх них работают СериализаторXDTO и механизм планов обмена. Всё это есть в платформе 8.3 без внешних компонент.
Частое заблуждение — что XML в 1С «открывают» только типовой обработкой. Типовые обработки удобны для переноса справочников между одинаковыми базами. Но прайс поставщика, выгрузку для сайта или ответ веб-сервиса проще и надёжнее разобрать своим кодом на 20–40 строк. Примеры ниже рабочие, их можно вставить во внешнюю обработку и запустить.
Как устроен XML-файл и какие объекты 1С за что отвечают
XML — текстовый файл с вложенными элементами. У элемента есть имя, атрибуты и содержимое: текст или другие элементы. Первая строка — объявление с версией и кодировкой.
<?xml version="1.0" encoding="UTF-8"?>
<Товары>
<Товар Код="00-001">
<Наименование>Бумага А4</Наименование>
<Цена>450.00</Цена>
</Товар>
</Товары>
Здесь Товары — корневой элемент, Код — атрибут, Бумага А4 — текстовое содержимое. Числа и даты в XML пишут в «машинном» виде: точка как разделитель, дата как 2026-10-07T00:00:00.
| Объект 1С | Для чего | Память |
|---|---|---|
ЧтениеXML | Последовательное чтение узел за узлом | Держит только текущий узел |
ЗаписьXML | Последовательная запись элементов, атрибутов, текста | Пишет сразу в файл или строку |
ПостроительDOM + ДокументDOM | Чтение всего дерева, поиск по имени, XPath | Весь документ в памяти |
СериализаторXDTO | Выгрузка и загрузка объектов 1С как XML | Работает поверх ЗаписьXML / ЧтениеXML |
ФабрикаXDTO | Работа по XML-схеме (пакеты XDTO) | Зависит от способа чтения |
Две служебные функции пригодятся везде: XMLСтрока(Значение) превращает число, дату или булево в строку по правилам XML, а XMLЗначение(Тип, Строка) делает обратное. Не пишите Число(Чтение.Значение): на строке 450.00 в русской локали это легко ломается, а XMLЗначение(Тип("Число"), ...) читает точку корректно.
Код, работающий с файлами, ставьте в процедуры с директивой &НаСервере, если файл лежит на сервере, и в &НаКлиенте — если на компьютере пользователя. Путь C:\Обмен\prices.xml на клиенте и на сервере 1С — это разные диски.
Чтение XML в 1С: потоковый разбор и DOM
Потоковое чтение через ЧтениеXML
Метод Прочитать() переходит к следующему узлу и возвращает Ложь, когда файл закончился. Тип узла смотрят в свойстве ТипУзла, имя — в Имя, текст — в Значение. Пример ниже разбирает файл из первого раздела в таблицу значений.
&НаСервере
Функция ПрочитатьТовары(ИмяФайла)
Товары = Новый ТаблицаЗначений;
Товары.Колонки.Добавить("Код");
Товары.Колонки.Добавить("Наименование");
Товары.Колонки.Добавить("Цена");
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
ТекущаяСтрока = Неопределено;
ТекущееПоле = "";
Пока Чтение.Прочитать() Цикл
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
Если Чтение.Имя = "Товар" Тогда
ТекущаяСтрока = Товары.Добавить();
ТекущаяСтрока.Код = Чтение.ЗначениеАтрибута("Код");
Иначе
ТекущееПоле = Чтение.Имя;
КонецЕсли;
ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.Текст И ТекущаяСтрока <> Неопределено Тогда
Если ТекущееПоле = "Наименование" Тогда
ТекущаяСтрока.Наименование = Чтение.Значение;
ИначеЕсли ТекущееПоле = "Цена" Тогда
ТекущаяСтрока.Цена = XMLЗначение(Тип("Число"), Чтение.Значение);
КонецЕсли;
ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
ТекущееПоле = "";
КонецЕсли;
КонецЦикла;
Чтение.Закрыть();
Возврат Товары;
КонецФункции
Сброс ТекущееПоле на конце элемента защищает от того, что текст попадёт не в ту колонку. Если атрибута нет, ЗначениеАтрибута вернёт Неопределено — проверьте это перед поиском товара по коду.
Чтение через DOM
DOM удобнее, когда структура глубокая или нужно сначала найти узел, а потом вернуться к соседнему. Цена — весь файл в оперативной памяти.
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
Построитель = Новый ПостроительDOM;
Документ = Построитель.Прочитать(Чтение);
Чтение.Закрыть();
Узлы = Документ.ПолучитьЭлементыПоИмени("Товар");
Для Каждого Узел Из Узлы Цикл
Код = Узел.ПолучитьАтрибут("Код");
СписокИмён = Узел.ПолучитьЭлементыПоИмени("Наименование");
Если СписокИмён.Количество() > 0 Тогда
Наименование = СписокИмён.Элемент(0).ТекстовоеСодержимое;
КонецЕсли;
КонецЦикла;
Если в файле объявлено пространство имён (атрибут xmlns), поиск по XPath потребует разыменователя пространств имён РазыменовательПространствИменDOM. Для поиска по простому имени элемента он не нужен.
Запись XML в 1С: как сформировать файл обмена
ЗаписьXML пишет строго последовательно: открыл элемент — записал атрибуты — записал содержимое — закрыл. Атрибуты пишут сразу после ЗаписатьНачалоЭлемента, до любого текста. Пример выгружает справочник номенклатуры в формат из первого раздела.
&НаСервере
Процедура ВыгрузитьНоменклатуру(ИмяФайла)
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл(ИмяФайла, "UTF-8");
Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("Товары");
Выборка = Справочники.Номенклатура.Выбрать();
Пока Выборка.Следующий() Цикл
Если Выборка.ЭтоГруппа Тогда
Продолжить;
КонецЕсли;
Запись.ЗаписатьНачалоЭлемента("Товар");
Запись.ЗаписатьАтрибут("Код", СокрЛП(Выборка.Код));
Запись.ЗаписатьНачалоЭлемента("Наименование");
Запись.ЗаписатьТекст(Выборка.Наименование);
Запись.ЗаписатьКонецЭлемента();
Запись.ЗаписатьКонецЭлемента(); // Товар
КонецЦикла;
Запись.ЗаписатьКонецЭлемента(); // Товары
Запись.Закрыть();
КонецПроцедуры
Что важно при записи:
- 🔤 Кодировка. Указывайте
"UTF-8"явно, если принимающая сторона не требует иного. Если требуетwindows-1251— укажите её, и объявление в файле совпадёт с реальной кодировкой. - 🔢 Числа и даты. Пишите через
XMLСтрока():Запись.ЗаписатьТекст(XMLСтрока(Цена)). Тогда в файле будет450, а не450,00с неразрывным пробелом в разряде тысяч. - 🧩 Спецсимволы. Амперсанд и угловые скобки
ЗаписатьТекстэкранирует сам. Руками собирать XML склейкой строк не нужно — именно так появляются «битые» файлы. - 📄 Строка вместо файла. Для веб-сервиса откройте запись методом
УстановитьСтроку(), а готовый текст получите изЗакрыть().
Если нужно выгрузить не «свой» формат, а объект 1С целиком со всеми реквизитами и табличными частями, вместо ручной записи используйте сериализацию: СериализаторXDTO.ЗаписатьXML(Запись, СправочникОбъект). Обратная операция — СериализаторXDTO.ПрочитатьXML(Чтение).
Обмен данными между конфигурациями 1С через XML
Здесь три уровня — от готового к своему коду.
| Способ | Когда подходит | Ограничения |
|---|---|---|
| Синхронизация данных в типовых (БП, УТ, ЗУП, КА, ERP) | Типовой обмен между типовыми конфигурациями | Настраивается только из поддерживаемых пар |
| Универсальный обмен через правила конвертации | Разные или доработанные конфигурации | Нужно написать или найти правила в «Конвертации данных» |
| Типовая обработка выгрузки и загрузки XML | Перенос объектов между базами одной конфигурации | Метаданные в обеих базах должны совпадать |
| Свой код на планах обмена | Распределённые и собственные обмены | Код и тестирование — на вас |
Синхронизация в типовых конфигурациях
В БП 3.0, УТ 11 и ЗУП 3.1 обмен включают в Администрирование → Синхронизация данных. Сначала ставят флажок использования синхронизации и задают префикс информационной базы, затем добавляют обмен с нужной программой. Данные идут в формате EnterpriseData — это XML по опубликованной схеме. Транспорт выбирается при настройке: общий каталог, FTP, электронная почта или прямое подключение через интернет
.
Префиксы баз в обмене должны различаться. Иначе номера документов из двух баз будут совпадать, и найти, какой счёт откуда пришёл, станет трудно.
Обмен своим кодом через план обмена
Каркас выгрузки по плану обмена: сообщение открывается для узла-получателя, внутрь сериализуются зарегистрированные изменения.
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл(ИмяФайла, "UTF-8");
ЗаписьСообщения = ПланыОбмена.СоздатьЗаписьСообщения();
ЗаписьСообщения.НачатьЗапись(Запись, Узел);
Выборка = ПланыОбмена.ВыбратьИзменения(Узел, ЗаписьСообщения.НомерСообщения);
Пока Выборка.Следующий() Цикл
ЗаписатьXML(Запись, Выборка.Получить());
КонецЦикла;
ЗаписьСообщения.ЗакончитьЗапись();
Запись.Закрыть();
Загрузка на стороне получателя:
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ИмяФайла);
ЧтениеСообщения = ПланыОбмена.СоздатьЧтениеСообщения();
ЧтениеСообщения.НачатьЧтение(Чтение);
ПланыОбмена.УдалитьРегистрациюИзменений(ЧтениеСообщения.Отправитель, ЧтениеСообщения.НомерПринятого);
Пока ВозможностьЧтенияXML(Чтение) Цикл
Данные = ПрочитатьXML(Чтение);
Данные.ОбменДанными.Отправитель = ЧтениеСообщения.Отправитель;
Данные.ОбменДанными.Загрузка = Истина;
Данные.Записать();
КонецЦикла;
ЧтениеСообщения.ЗакончитьЧтение();
Чтение.Закрыть();
Свойство ОбменДанными.Загрузка = Истина отключает проверки и обработчики ПередЗаписью и ПриЗаписи в объектах. Это ускоряет загрузку, но ответственность за целостность данных переходит на отправителя. А Отправитель не даёт загруженному изменению вернуться обратно тому же узлу.
Ошибки при работе с XML и как их разбирать
Любой разбор чужого файла оборачивайте в Попытка ... Исключение, а текст ошибки пишите в журнал регистрации или выводите пользователю через ОписаниеОшибки(). В тексте ошибки разбора платформа обычно указывает строку и позицию — открывайте файл в редакторе с нумерацией строк и смотрите это место.
Ещё одна частая причина — пространства имён. Если в файле элементы записаны с префиксом (<ns1:Товар>), свойство Чтение.Имя вернёт имя вместе с префиксом, и сравнение с "Товар" не сработает. Сравнивайте по Чтение.ЛокальноеИмя — оно без префикса.
Большие XML-файлы: как не упереться в память и время
Файл на сотни мегабайт — обычное дело для выгрузки остатков или полной синхронизации. Что помогает:
- Только потоковое чтение.
ПостроительDOMзагружает всё дерево в память, на большом файле это гарантированный вылет рабочего процесса.ЧтениеXMLдержит один узел. - Пропуск ненужных веток. Метод
Пропустить()уЧтениеXMLперескакивает текущий элемент вместе со всеми вложенными. Так разделы, которые вам не нужны, не разбираются вовсе. - Транзакции порциями. Записывайте объекты пачками по 500–1000 штук внутри
НачатьТранзакцию()/ЗафиксироватьТранзакцию(). Одна транзакция на весь файл держит блокировки часами, а без транзакций каждая запись фиксируется отдельно и медленнее. - Кэш поиска. Если для каждой строки прайса ищете товар по коду, сначала одним запросом получите соответствие «код → ссылка» и ищите в нём. Тысячи одиночных
НайтиПоКоду— главный тормоз загрузки. - Сжатие. XML жмётся в разы. Для передачи упакуйте файл объектом
ЗаписьZipФайла, на приёме распакуйтеЧтениеZipФайла. - Работа на сервере. Разбирайте файл в серверной процедуре, а не на клиенте: не будет лишних серверных вызовов на каждую строку.
Если загрузка всё равно идёт долго, запустите её фоновым заданием. Пользователь не держит открытую форму, а результат и ошибки можно записать в журнал регистрации.
XML и веб-сервисы SOAP в 1С
SOAP — тот же XML, только упакованный в конверт и переданный по HTTP. Платформа скрывает конверт: вы вызываете операцию как обычную функцию.
Обращение к внешнему сервису
Определения = Новый WSОпределения("https://example.ru/service?wsdl", "user", "password");
Прокси = Новый WSПрокси(Определения, "http://example.ru/namespace", "PriceService", "PriceServiceSoap");
Результат = Прокси.GetPrice("00-001");
Пространство имён, имя сервиса и имя точки подключения берут из WSDL: элементы targetNamespace, service и port. Если сервис часто нужен, создайте в конфигураторе объект WS-ссылка: WSDL импортируется в конфигурацию, и не придётся загружать описание при каждом вызове.
Свой веб-сервис в 1С
- В конфигураторе добавьте объект
Web-сервисы, задайте пространство имён и операции с параметрами. - Для каждой операции напишите функцию-обработчик в модуле веб-сервиса.
- Опубликуйте базу:
Администрирование → Публикация на веб-серверев конфигураторе. Нужен установленный Apache или IIS на машине, где выполняется публикация. - Проверьте WSDL в браузере по адресу публикации с
?wsdlна конце.
Если внешняя система ждёт не SOAP, а «голый» XML по HTTP, используйте HTTPСоединение и HTTPЗапрос: тело запроса формируется через ЗаписьXML с УстановитьСтроку(), ответ разбирается ЧтениеXML.УстановитьСтроку().
Готовые решения для типичных задач с XML
| Задача | Чем решать |
|---|---|
| Загрузить прайс поставщика в номенклатуру и цены | Внешняя обработка с ЧтениеXML и кэшем «код → ссылка» |
| Выгрузить каталог и остатки на сайт | Регламентное задание с ЗаписьXML, файл в каталог или на FTP |
| Перенести справочники между копиями одной базы | Типовая обработка выгрузки и загрузки XML или СериализаторXDTO |
| Связать БП с УТ или ЗУП | Синхронизация данных, формат EnterpriseData |
| Обмен с доработанной или нетиповой базой | Правила из «Конвертации данных» и универсальный обмен |
| Принять заказы из внешней системы онлайн | Свой веб-сервис или HTTP-сервис |
Перед первой загрузкой в рабочую базу прогоните файл на копии. Загрузка с ОбменДанными.Загрузка = Истина не проверяет данные, и ошибочный файл может испортить тысячи объектов за один запуск. Сделайте резервную копию базы
до запуска.