Объект XDTO в 1С: от пакета до выгрузки в XML
Содержание
Объект XDTO создают через фабрику: Объект = ФабрикаXDTO.Создать(Тип), где Тип берут методом ФабрикаXDTO.Тип(URIПространстваИмён, ИмяТипа). Сам тип и его свойства заранее описывают в XDTO-пакете — он лежит в дереве конфигурации в ветке Общие → XDTO-пакеты. После заполнения свойств объект сериализуют в XML методом ФабрикаXDTO.ЗаписатьXML.
XDTO (XML Data Transfer Objects) — это механизм платформы 8.3 для работы с XML по строгой схеме. Вы описываете структуру данных один раз, а дальше платформа сама следит за типами, обязательными полями и порядком элементов. На этом построены универсальный обмен, веб-сервисы и выгрузка в сторонние системы. Ниже — весь путь: пакет, типы, фабрика, заполнение, выгрузка и отладка.
Что такое XDTO и когда он нужен
XDTO описывает данные как набор типизированных объектов, привязанных к XML-схеме (XSD). У каждого типа есть пространство имён (URI) и список свойств с явными типами. Это отличает XDTO от «ручного» формирования XML через ЗаписьXML, где за правильность структуры отвечает только программист.
Когда XDTO оправдан:
- 🔁 обмен данными между конфигурациями 1С по единому формату (EnterpriseData, CommerceML);
- 🌐 веб-сервисы и HTTP-сервисы — тело SOAP-запроса платформа собирает именно через XDTO;
- 📤 выгрузка в учётные системы партнёра, которые требуют XML по согласованной XSD;
- 🧩 сериализация прикладных объектов (справочников, документов) через
СериализаторXDTO.
Если формат простой и одноразовый, хватит и обычной записи XML. Но как только появляется внешняя схема и требование «валидный XML по XSD» — удобнее XDTO: он не даст записать строку туда, где ждут число, и подскажет про незаполненное обязательное свойство.
Модель XDTO двухуровневая. Верхний уровень — типы и фабрика (то, с чем вы пишете код): объектные типы, типы значений, свойства. Нижний уровень — XML-схема (XSD), по которой эти типы построены. Когда вы рисуете пакет в конфигураторе, платформа по нему строит схему; когда импортируете чужую XSD — наоборот, из схемы получаются типы. Понимание этой связки сразу снимает половину вопросов: «почему свойство стало атрибутом», «откуда взялось пространство имён», «почему тип называется именно так».
Базовые типы (строка, число, дата, булево) живут в пространстве имён http://www.w3.org/2001/XMLSchema. Ваши собственные типы — в том URI, который вы зададите пакету.
Создаём XDTO-пакет в конфигурации
Пакет — это контейнер для ваших типов. Он хранится прямо в конфигурации.
- Откройте конфигуратор, в дереве конфигурации найдите ветку
Общие → XDTO-пакеты. - Правой кнопкой →
Добавить. Задайте имя пакета, напримерКаталогТоваров. - В свойстве
Пространство имёнукажите URI — уникальный идентификатор схемы, напримерhttp://example.com/catalog. Это не адрес в интернете, а именно идентификатор; важно, чтобы он совпадал с тем, что ждёт получатель данных.
Если у партнёра уже есть готовая XSD-схема, пакет не рисуют руками. Вместо этого импортируют схему: в контекстном меню ветки XDTO-пакеты выберите команду импорта XML-схемы и укажите файл .xsd. Платформа сама создаст пакет, типы и свойства по описанию. Перед импортом чужой схемы сохраните резервную копию конфигурации — откат импорта вручную трудоёмок.
URI пространства имён должен совпадать у отправителя и получателя до символа. Разный регистр или лишний слеш в конце — и тип при чтении не найдётся.
Описываем типы объектов и их свойства
Внутри пакета создают типы двух видов:
- Тип объекта (
ОбъектныйТип) — сложная сущность со свойствами: товар, контрагент, строка документа. - Тип значения (
ТипЗначения) — простой тип, например перечисление допустимых строковых значений или число с ограничением.
Для нашего примера добавим в пакет КаталогТоваров объектный тип Товар. У него будут свойства:
| Свойство | Тип | Форма | Множественность |
|---|---|---|---|
Артикул | string (из XMLSchema) | Атрибут | 1..1 |
Наименование | string | Элемент | 1..1 |
Цена | decimal | Элемент | 0..1 |
Характеристики | тип Характеристика | Элемент | 0..∞ |
Где что задаётся в свойствах каждого свойства типа:
- Тип — выбирают из списка. Для простых значений раскройте пространство имён
http://www.w3.org/2001/XMLSchemaи возьмитеstring,decimal,int,boolean,dateTime. - Форма определяет, как свойство ляжет в XML:
Атрибут— атрибутом тега,Элемент— вложенным тегом,Текст— текстом элемента. - Нижняя граница и Верхняя граница — множественность.
Нижняя граница = 1делает свойство обязательным.Верхняя граница = -1(без ограничения) превращает свойство в коллекцию.
Добавьте вторым объектным типом Характеристика со свойствами Имя (string) и Значение (string). Именно его мы укажем в типе свойства Характеристики у Товара.
Если свойство должно быть списком, выставьте верхнюю границу больше 1 (или -1). В коде обращение к такому свойству вернёт не одно значение, а СписокXDTO с методами Добавить(), Количество(), Получить(Индекс).
Ещё две настройки пригодятся на реальных схемах. Если тип свойства должен допускать несколько вариантов (например, то строку, то число), в XDTO используют абстрактный базовый тип, а конкретные типы наследуют от него — тогда в объект кладут любой из наследников. А чтобы свойство могло быть пустым по значению (а не просто отсутствовать), ему разрешают nil: в схеме это nillable, в объекте такому свойству присваивают Неопределено. Путать «свойство не задано» и «свойство задано пустым» не стоит — для внешней системы это разные ситуации.
Получаем фабрику и создаём объект
Фабрика XDTO — это «завод», который умеет создавать объекты описанных типов и превращать их в XML и обратно. В платформе всегда доступна глобальная фабрика ФабрикаXDTO: в неё автоматически включены все пакеты вашей конфигурации. Для типов из конфигурации отдельную фабрику создавать не нужно.
Получаем тип и создаём объект:
// Тип берём из глобальной фабрики по URI пакета и имени типа
ТипТовар = ФабрикаXDTO.Тип("http://example.com/catalog", "Товар");
// Создаём пустой объект XDTO
Товар = ФабрикаXDTO.Создать(ТипТовар);
Отдельная фабрика нужна в одном случае: схема пришла в виде внешнего .xsd-файла и в конфигурацию её не добавляли. Тогда схему читают и строят фабрику из неё:
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл("C:\Обмен\catalog.xsd");
Схема = ПрочитатьСхемуXML(Чтение);
Чтение.Закрыть();
НаборСхем = Новый НаборСхемXML;
НаборСхем.Добавить(Схема);
МояФабрика = Новый ФабрикаXDTO(НаборСхем);
ТипТовар = МояФабрика.Тип("http://example.com/catalog", "Товар");
Дальше вся работа идёт через МояФабрика вместо глобальной. Главное правило: объект, созданный одной фабрикой, записывайте и читайте той же фабрикой — иначе типы не совпадут.
Заполняем свойства и работаем с коллекциями
К свойствам объекта обращаются через точку по имени или через квадратные скобки — удобно, когда имя свойства в переменной.
Товар.Артикул = "DR-150";
Товар.Наименование = "Дрель аккумуляторная";
Товар.Цена = 5490;
// То же самое через скобки
Товар["Наименование"] = "Дрель аккумуляторная";
Платформа контролирует типы: присвоить строку свойству с типом decimal не получится — будет ошибка ещё до записи XML. Это и есть главный плюс XDTO перед ручной сборкой.
Свойство-коллекция (Характеристики) ведёт себя как список. Каждый элемент коллекции — тоже объект XDTO, его сначала создают, потом добавляют:
ТипХарактеристики = ФабрикаXDTO.Тип("http://example.com/catalog", "Характеристика");
Цвет = ФабрикаXDTO.Создать(ТипХарактеристики);
Цвет.Имя = "Цвет";
Цвет.Значение = "синий";
Товар.Характеристики.Добавить(Цвет);
Мощность = ФабрикаXDTO.Создать(ТипХарактеристики);
Мощность.Имя = "Мощность, Вт";
Мощность.Значение = "600";
Товар.Характеристики.Добавить(Мощность);
Обойти уже заполненную коллекцию можно обычным циклом:
Для Каждого Характеристика Из Товар.Характеристики Цикл
Сообщить(Характеристика.Имя + ": " + Характеристика.Значение);
КонецЦикла;
Необязательное свойство (нижняя граница 0) можно не заполнять. Проверить, установлено ли оно, помогает метод объекта Установлено(Свойство) — он вернёт Истина, если значение задано.
Перед выгрузкой объект полезно проверить на соответствие схеме:
Товар.Проверить();
Метод Проверить() вызовет исключение, если пропущено обязательное свойство или нарушены ограничения типа. Лучше поймать его заранее, чем получить невалидный XML на стороне получателя.
Сериализуем объект и выгружаем в XML
Готовый объект превращают в XML всё той же фабрикой. Записывать можно в строку (например, для тела веб-сервиса) или сразу в файл.
В строку — когда XML нужен в памяти:
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
ФабрикаXDTO.ЗаписатьXML(Запись, Товар);
СтрокаXML = Запись.Закрыть();
В файл — когда нужна выгрузка на диск:
Запись = Новый ЗаписьXML;
Запись.ОткрытьФайл("C:\Обмен\catalog.xml");
ФабрикаXDTO.ЗаписатьXML(Запись, Товар);
Запись.Закрыть();
Результат для нашего примера будет примерно таким:
<Товар Артикул="DR-150" xmlns="http://example.com/catalog">
<Наименование>Дрель аккумуляторная</Наименование>
<Цена>5490</Цена>
<Характеристики><Имя>Цвет</Имя><Значение>синий</Значение></Характеристики>
<Характеристики><Имя>Мощность, Вт</Имя><Значение>600</Значение></Характеристики>
</Товар>
Обратная операция — прочитать XML в объект XDTO:
Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл("C:\Обмен\catalog.xml");
Товар = ФабрикаXDTO.ПрочитатьXML(Чтение, ТипТовар);
Чтение.Закрыть();
Третий параметр ПрочитатьXML (ожидаемый тип) можно не указывать, если в XML корректно записано пространство имён и имя корневого типа — фабрика определит тип сама. Но явный тип делает чтение надёжнее.
Пара деталей по выгрузке в файл. По умолчанию ЗаписьXML ставит XML-декларацию и кодировку UTF-8 — для большинства получателей это норма. Если партнёр требует Windows-1251 или без декларации, параметры задают до записи: кодировку — вторым аргументом ОткрытьФайл, declaration и форматирование — свойствами объекта ЗаписьXML. Несколько объектов в один файл кладут так: открыли запись, записали корневой элемент вручную через ЗаписатьНачалоЭлемента, затем в цикле вызвали ЗаписатьXML для каждого объекта и закрыли корневой элемент. Один вызов ЗаписатьXML пишет ровно один объект XDTO.
Отдельно стоит СериализаторXDTO — глобальный объект, который сериализует в XML готовые прикладные объекты: элементы справочников, документы, записи регистров. Описывать для них XDTO-пакет вручную не нужно, платформа строит схему сама. Это другой инструмент, но из той же механики:
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
СериализаторXDTO.ЗаписатьXML(Запись, ЭлементСправочника);
СтрокаXML = Запись.Закрыть();
Разбираем частые ошибки и способы отладки
Большинство проблем с XDTO сводится к несовпадению схемы и данных. Вот по каким симптомам их быстро опознать.
ФабрикаXDTO.Тип(...). Сверьте URI посимвольно со свойством пакета: лишний слеш или другой регистр ломают поиск.Число(Строка), XMLЗначение(Тип, Строка).Проверить() до записи, чтобы увидеть, какое именно поле пустое.ФабрикаXDTO даёт несовпадение типов.Приёмы отладки, которые экономят время:
- Смотрите XML глазами. Запишите объект в строку через
УстановитьСтроку()и выведитеСообщить(СтрокаXML). Сразу видно, какие теги и атрибуты реально сформировались. - Валидируйте до отправки. Вызов
Товар.Проверить()ловит неполные данные на вашей стороне, а не на стороне партнёра. - Перебирайте свойства типа. Коллекция
ТипТовар.Свойствасодержит все свойства с именами и типами — удобно, когда схема чужая и под рукой нет описания:
Для Каждого Свойство Из ТипТовар.Свойства Цикл
Сообщить(Свойство.Имя + " — " + Строка(Свойство.Тип));
КонецЦикла;
- Проверяйте форму записи. Если ждёте атрибут, а получаете вложенный тег (или наоборот), значит у свойства неверно выставлена
Формав пакете.
Если фабрику строите из внешней XSD, а схема ссылается на другие схемы (import/include), добавьте в НаборСхемXML все связанные файлы — иначе часть типов не соберётся.
Чем XDTO отличается от обычной записи через ЗаписьXML?
ЗаписьXML пишет любой XML без контроля структуры — ответственность на программисте. XDTO работает по схеме: контролирует типы, обязательность и форму свойств, поэтому невалидный XML получить сложнее.Нужно ли создавать свою фабрику для типов из конфигурации?
ФабрикаXDTO уже содержит все XDTO-пакеты конфигурации. Собственную фабрику строят только из внешней XSD-схемы, которой в конфигурации нет.Как добавить несколько значений в одно свойство?
СписокXDTO, и элементы добавляют методом Добавить().Почему при чтении XML выдаёт, что тип не найден?
Можно ли сериализовать справочник или документ без описания пакета?
СериализаторXDTO — он строит схему для прикладных объектов автоматически. Отдельный XDTO-пакет под них описывать не требуется.