XML в 1С 8.3 на практике: от разбора файла до обмена между базами

· 10 мин

Содержание

Работа с 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-файлы: как не упереться в память и время

Файл на сотни мегабайт — обычное дело для выгрузки остатков или полной синхронизации. Что помогает:

  1. Только потоковое чтение. ПостроительDOM загружает всё дерево в память, на большом файле это гарантированный вылет рабочего процесса. ЧтениеXML держит один узел.
  2. Пропуск ненужных веток. Метод Пропустить() у ЧтениеXML перескакивает текущий элемент вместе со всеми вложенными. Так разделы, которые вам не нужны, не разбираются вовсе.
  3. Транзакции порциями. Записывайте объекты пачками по 500–1000 штук внутри НачатьТранзакцию() / ЗафиксироватьТранзакцию(). Одна транзакция на весь файл держит блокировки часами, а без транзакций каждая запись фиксируется отдельно и медленнее.
  4. Кэш поиска. Если для каждой строки прайса ищете товар по коду, сначала одним запросом получите соответствие «код → ссылка» и ищите в нём. Тысячи одиночных НайтиПоКоду — главный тормоз загрузки.
  5. Сжатие. XML жмётся в разы. Для передачи упакуйте файл объектом ЗаписьZipФайла, на приёме распакуйте ЧтениеZipФайла.
  6. Работа на сервере. Разбирайте файл в серверной процедуре, а не на клиенте: не будет лишних серверных вызовов на каждую строку.

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

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С

  1. В конфигураторе добавьте объект Web-сервисы, задайте пространство имён и операции с параметрами.
  2. Для каждой операции напишите функцию-обработчик в модуле веб-сервиса.
  3. Опубликуйте базу: Администрирование → Публикация на веб-сервере в конфигураторе. Нужен установленный Apache или IIS на машине, где выполняется публикация.
  4. Проверьте WSDL в браузере по адресу публикации с ?wsdl на конце.

Если внешняя система ждёт не SOAP, а «голый» XML по HTTP, используйте HTTPСоединение и HTTPЗапрос: тело запроса формируется через ЗаписьXML с УстановитьСтроку(), ответ разбирается ЧтениеXML.УстановитьСтроку().

Готовые решения для типичных задач с XML

ЗадачаЧем решать
Загрузить прайс поставщика в номенклатуру и ценыВнешняя обработка с ЧтениеXML и кэшем «код → ссылка»
Выгрузить каталог и остатки на сайтРегламентное задание с ЗаписьXML, файл в каталог или на FTP
Перенести справочники между копиями одной базыТиповая обработка выгрузки и загрузки XML или СериализаторXDTO
Связать БП с УТ или ЗУПСинхронизация данных, формат EnterpriseData
Обмен с доработанной или нетиповой базойПравила из «Конвертации данных» и универсальный обмен
Принять заказы из внешней системы онлайнСвой веб-сервис или HTTP-сервис

Перед первой загрузкой в рабочую базу прогоните файл на копии. Загрузка с ОбменДанными.Загрузка = Истина не проверяет данные, и ошибочный файл может испортить тысячи объектов за один запуск. Сделайте резервную копию базы до запуска.

Частые вопросы

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