Как устроена работа с XDTO в 1С:Предприятии 8.3 — от XSD-схемы до обмена
Содержание
Работа с XDTO в 1С сводится к двум объектам платформы. ФабрикаXDTO знает типы данных из XDTO-пакетов и XSD-схем и строит по ним объекты. СериализаторXDTO переводит объекты конфигурации (справочники, документы, регистры) в XML или JSON и обратно. Всё остальное — обмен, веб-сервисы, разбор чужих файлов — надстройка над этими двумя.
Частое заблуждение: «XDTO — это для веб-сервисов, для обычного обмена хватит ЗаписьXML». На деле XDTO выгоднее и в файловом обмене. Схема сама проверяет обязательные поля, типы и порядок элементов, а вы не пишете сотни строк ручного разбора узлов.
Из чего состоит XDTO: модель типов и данных
XDTO (XML Data Transfer Objects) описывает данные так же, как XML Schema. Есть пространство имён (URI), в нём — типы, у типов — свойства.
Типы делятся на два вида:
- 🧱 Тип значения (
ТипЗначенияXDTO) — простое значение: строка, число, дата, перечисление с фасетами (длина, шаблон, список допустимых значений). - 📦 Тип объекта (
ТипОбъектаXDTO) — составной объект со свойствами. Свойство может хранить значение или вложенный объект.
У каждого свойства есть важные характеристики:
| Характеристика | Что задаёт | Чем грозит ошибка |
|---|---|---|
| Нижняя граница | 0 — необязательное, 1 — обязательное | Проверка падает, если поле не заполнено |
| Верхняя граница | 1 — одно значение, -1 — список | При -1 свойство становится СписокXDTO |
| Возможно пустое (nillable) | Допускает xsi:nil="true" | Без него пустой элемент не пройдёт проверку |
| Форма | Элемент, атрибут или текст | Атрибут нельзя прочитать как элемент |
Соответствие типов XML Schema и 1С простое: xs:string → Строка, xs:decimal и xs:int → Число, xs:dateTime и xs:date → Дата, xs:boolean → Булево. Двоичные данные (xs:base64Binary) превращаются в ДвоичныеДанные.
Когда в коде вы обращаетесь Объект.Номер, платформа ищет свойство по имени из схемы. Регистр букв важен: number и Number — разные свойства.
Как создать XDTO-пакет и подключить XSD-схему
Есть два пути. Первый — статический пакет в конфигурации. Второй — фабрика, собранная из XSD прямо во время работы.
XDTO-пакет в конфигураторе
- Откройте конфигурацию в конфигураторе.
- В дереве перейдите в
Общие → XDTO-пакеты. - Если у вас есть готовая XSD от контрагента или госоргана, вызовите контекстное меню ветки и выберите импорт XML-схемы. Пакет и все типы создадутся автоматически.
- Если схемы нет, добавьте пакет вручную, задайте URI пространства имён (например,
http://example.org/orders/1.0) и опишите типы в редакторе пакета. - Обновите конфигурацию базы данных.
После этого типы пакета доступны через глобальную ФабрикаXDTO без дополнительных действий.
Если вы правите типовую конфигурацию, добавление пакета снимает её с полной поддержки в этой части. Для типовых баз удобнее второй путь — фабрика из XSD-файла, которая ничего не меняет в конфигурации.
Фабрика из XSD без изменения конфигурации
Схему можно прочитать из файла и построить отдельную фабрику. Это удобно в обработках и расширениях.
Функция ФабрикаИзXSD(ПутьКФайлуXSD)
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлуXSD);
ПостроительDOM = Новый ПостроительDOM;
ДокументDOM = ПостроительDOM.Прочитать(Чтение);
Чтение.Закрыть();
ПостроительСхем = Новый ПостроительСхемXML;
Схема = ПостроительСхем.СоздатьСхемуXML(ДокументDOM);
НаборСхем = Новый НаборСхемXML;
НаборСхем.Добавить(Схема);
Возврат Новый ФабрикаXDTO(НаборСхем);
КонецФункции
Если схема импортирует другие XSD (xs:import), добавьте в НаборСхем все файлы, иначе фабрика не найдёт внешние типы.
Как создать и заполнить объект по типу
URI = "http://example.org/orders/1.0";
ТипЗаказ = ФабрикаXDTO.Тип(URI, "Order");
ТипСтрока = ФабрикаXDTO.Тип(URI, "OrderLine");
Заказ = ФабрикаXDTO.Создать(ТипЗаказ);
Заказ.Number = "ЗК-000125";
Заказ.Date = ТекущаяДатаСеанса();
СтрокаЗаказа = ФабрикаXDTO.Создать(ТипСтрока);
СтрокаЗаказа.Sku = "A-100";
СтрокаЗаказа.Quantity = 3;
СтрокаЗаказа.Price = 1250.50;
// Свойство Lines имеет верхнюю границу -1, это СписокXDTO
Заказ.Lines.Добавить(СтрокаЗаказа);
Для свойства-списка нельзя писать Заказ.Lines = СтрокаЗаказа: так вы перезапишете список одним элементом или получите ошибку типа. Только Добавить().
Сериализация и десериализация объектов через XDTO
Здесь две разные задачи, и их часто путают.
| Задача | Чем делать | Что получится |
|---|---|---|
| Выгрузить справочник или документ «как есть» | СериализаторXDTO | XML в пространстве имён платформы, ссылки в виде UUID |
| Сформировать файл по чужой схеме | ФабрикаXDTO + свой пакет | XML строго по XSD контрагента |
| Передать объект в JSON | СериализаторXDTO.ЗаписатьJSON | JSON с типами платформы |
Объект XDTO → XML-строка и обратно
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку("UTF-8");
Запись.ЗаписатьОбъявлениеXML();
ФабрикаXDTO.ЗаписатьXML(Запись, Заказ, "Order", URI);
ТекстXML = Запись.Закрыть();
Чтение выполняется зеркально:
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(ТекстXML);
Заказ = ФабрикаXDTO.ПрочитатьXML(Чтение, ФабрикаXDTO.Тип(URI, "Order"));
Чтение.Закрыть();
Для Каждого СтрокаЗаказа Из Заказ.Lines Цикл
Сообщить(СтрокаЗаказа.Sku + ": " + Формат(СтрокаЗаказа.Quantity, "ЧГ=0"));
КонецЦикла;
Объекты конфигурации через СериализаторXDTO
Глобальный СериализаторXDTO умеет записывать почти любой объект конфигурации, ссылку, таблицу значений, структуру или набор записей регистра.
// Выгрузка элемента справочника
Объект = Ссылка.ПолучитьОбъект();
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\Exchange\item.xml");
СериализаторXDTO.ЗаписатьXML(Запись, Объект, НазначениеТипаXML.Явное);
Запись.Закрыть();
// Загрузка в другой базе с той же структурой
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл("C:\Exchange\item.xml");
Объект = СериализаторXDTO.ПрочитатьXML(Чтение);
Чтение.Закрыть();
Объект.ОбменДанными.Загрузка = Истина;
Объект.Записать();
Флаг ОбменДанными.Загрузка = Истина отключает проверки и бизнес-логику в обработчиках записи. Так работают типовые механизмы выгрузки и загрузки данных.
Загрузка с флагом Загрузка = Истина пропускает проверку заполнения и проведение — сначала прогоните её на копии базы.
Важные особенности этого приёма:
- 🔑 Ссылки пишутся по UUID. Если в базе-приёмнике нет объекта с таким UUID, после загрузки останется «битая» ссылка.
- 🧩 Структура метаданных в обеих базах должна совпадать. Лишний реквизит в XML вызовет ошибку чтения.
- 🔄 Для JSON используйте
ЗаписьJSONиСериализаторXDTO.ЗаписатьJSON(Запись, Значение, НазначениеТипаXML.Явное); чтение —СериализаторXDTO.ПрочитатьJSON.
НазначениеТипаXML.Явное добавляет атрибут xsi:type. Без него при чтении значения составного типа (например, реквизита «Строка или Число») платформа не сможет понять, что лежит в элементе.
Проверка данных и обработка ошибок XDTO
XDTO проверяет данные в двух местах: при чтении XML и по команде Проверить(). Пользуйтесь вторым до отправки — так ошибка всплывёт у вас, а не на стороне получателя.
Попытка
Заказ.Проверить();
Исключение
ТекстОшибки = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Обмен.XDTO", УровеньЖурналаРегистрации.Ошибка,,,
"Заказ " + Заказ.Number + ": " + ТекстОшибки);
ВызватьИсключение;
КонецПопытки;
Проверить() смотрит обязательные свойства, количество элементов в списках, фасеты простых типов (длина строки, шаблон, перечисление допустимых значений).
Чтение XML тоже оборачивайте в Попытка. Сообщения платформы начинаются с Ошибка преобразования данных XDTO или Ошибка проверки данных XDTO, дальше идут имя свойства и тип. Эту часть и надо читать.
Пустой элемент <Comment/> и отсутствующий элемент — не одно и то же. Если получатель ждёт пустой элемент, а свойство не помечено как nillable, присвойте пустую строку, а не Неопределено.
XDTO в веб-сервисах и HTTP-запросах
Свой веб-сервис на 1С
- В
Общие → Web-сервисыдобавьте сервис, задайте URI пространства имён. - В свойстве сервиса укажите XDTO-пакеты, типы которых будут параметрами и результатами.
- Опишите операции, для параметров выберите типы из пакета.
- Опубликуйте базу:
Администрирование → Публикация на веб-серверев конфигураторе.
В модуле операции параметр приходит уже готовым ОбъектXDTO. Возвращаете тоже объект, созданный через фабрику:
Функция ПолучитьЗаказ(НомерЗаказа)
Ответ = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип(URI, "Order"));
Ответ.Number = НомерЗаказа;
// ... заполнение из базы
Возврат Ответ;
КонецФункции
Подключение к чужому SOAP-сервису
Динамически, по адресу WSDL:
Определения = Новый WSОпределения("https://partner.example/ws/orders?wsdl");
Прокси = Новый WSПрокси(Определения,
"http://example.org/orders/1.0", "OrderService", "OrderServiceSoap");
Заказ = Прокси.ФабрикаXDTO.Создать(
Прокси.ФабрикаXDTO.Тип("http://example.org/orders/1.0", "Order"));
Берите Прокси.ФабрикаXDTO, а не глобальную ФабрикаXDTO: типы чужого сервиса есть только в фабрике прокси.
Статический вариант — импортировать WSDL в Общие → WS-ссылки. Тогда прокси создаётся через WSСсылки.<ИмяСсылки>.СоздатьWSПрокси(URI, ИмяСервиса, ИмяТочки) и WSDL не скачивается при каждом вызове.
REST и HTTP с XML-телом
Для HTTP-сервиса XDTO даёт только формирование и разбор тела. Транспорт — HTTPСоединение и HTTPЗапрос:
Запрос = Новый HTTPЗапрос("/api/orders");
Запрос.Заголовки.Вставить("Content-Type", "application/xml; charset=utf-8");
Запрос.УстановитьТелоИзСтроки(ТекстXML, КодировкаТекста.UTF8);
Соединение = Новый HTTPСоединение("partner.example", 443,,,,, Новый ЗащищенноеСоединениеOpenSSL);
Ответ = Соединение.ОтправитьДляОбработки(Запрос);
Если Ответ.КодСостояния = 200 Тогда
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(Ответ.ПолучитьТелоКакСтроку());
Результат = ФабрикаXDTO.ПрочитатьXML(Чтение, ФабрикаXDTO.Тип(URI, "OrderResult"));
КонецЕсли;
Проверяйте код ответа до разбора. Иначе на 500 вы получите HTML-страницу ошибки и запутанное исключение XDTO вместо понятного сообщения.
Большие объёмы данных: как ускорить XDTO
На файлах в десятки мегабайт и выгрузках на сотни тысяч объектов узкие места одни и те же.
- ⏱ Получайте типы один раз.
ФабрикаXDTO.Тип()внутри цикла на 100 000 строк — лишние 100 000 поисков. Сохраните тип в переменную до цикла. - 💾 Пишите в файл, а не в строку.
УстановитьСтроку()держит весь документ в памяти.ОткрытьФайл()пишет потоком. - 📖 Не читайте большой файл через DOM.
ПостроительDOMгрузит весь документ в память. Читайте потоком и разбирайте через XDTO по одному элементу. - 🌐 Кешируйте прокси.
Новый WSОпределениякаждый раз скачивает WSDL. Создайте прокси один раз на сеанс или используйте WS-ссылку. - 📦 Режьте пакеты. Отправка 50 000 строк одним SOAP-вызовом упирается в таймауты. Разбейте на порции по 500–1000 объектов.
Потоковое чтение крупного файла по элементам:
ТипСтрока = ФабрикаXDTO.Тип(URI, "OrderLine");
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл("C:\Exchange\big.xml");
ЕстьУзел = Чтение.Прочитать();
Пока ЕстьУзел Цикл
Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента
И Чтение.ЛокальноеИмя = "OrderLine" Тогда
// ПрочитатьXML сам переводит чтение за конец элемента
СтрокаЗаказа = ФабрикаXDTO.ПрочитатьXML(Чтение, ТипСтрока);
ОбработатьСтроку(СтрокаЗаказа);
Иначе
ЕстьУзел = Чтение.Прочитать();
КонецЕсли;
КонецЦикла;
Чтение.Закрыть();
Обратите внимание на ветку Иначе. Если звать Прочитать() сразу после ПрочитатьXML, вы перескочите следующий элемент OrderLine, когда он идёт вплотную к предыдущему. Это частая причина «потерянных» строк при загрузке.
При загрузке тысяч объектов через СериализаторXDTO записывайте их порциями в транзакциях по 100–500 штук. Одна огромная транзакция держит блокировки и при сбое откатывается вся.
Частые ошибки при работе с XDTO
- ❌ Глобальная фабрика вместо фабрики прокси. Тип «не найден», хотя он есть в WSDL.
- ❌ Разные URI в пакете и в файле. Достаточно отличия в одном символе или завершающем слэше — и XML не читается.
- ❌ Присвоение списка вместо
Добавить(). Остаётся один элемент или возникает ошибка типа. - ❌ Склейка числа со строкой без формата.
"Количество: " + 1500даст1 500с неразрывным пробелом, а получатель ждёт1500. ИспользуйтеФормат(Число, "ЧГ=0")или присваивайте число в свойство числового типа. - ❌ Нет
НазначениеТипаXML.Явноедля составных типов. Выгрузка проходит, а загрузка падает или ставит не тот тип. - ❌ Правка XSD без версии. Меняете схему — меняйте URI (
/1.0→/1.1), чтобы старые и новые клиенты не ломали друг друга.
Частые вопросы
Чем XDTO отличается от обычной ЗаписьXML?
ЗаписьXML пишет узлы по одному, структуру вы контролируете сами. XDTO строит документ по схеме и проверяет типы, обязательность и порядок элементов.Можно ли использовать XDTO в расширении конфигурации?
Как посмотреть, какие типы есть в фабрике?
ФабрикаXDTO.Пакеты, у каждого пакета — коллекцию типов. Удобно для отладки, когда неясно, какой URI использовать.Подходит ли XDTO для JSON?
СериализаторXDTO есть ЗаписатьJSON и ПрочитатьJSON. Для чужого JSON без схемы проще ПрочитатьJSON в структуру или соответствие.