Разработка и Конфигурация · 11 мин
Как создать список XDTO в 1С
Как создать список XDTO в 1С: работа с фабрикой XDTO, добавление элементов в список, сериализация в XML, типичные ошибки и примеры кода на встроенном языке.
Механизм XDTO (XML Data Transfer Objects) в 1С используется для обмена данными с внешними системами: веб-сервисами, другими базами 1С, банками и государственными порталами. Одна из самых частых задач при такой интеграции — сформировать в XML-структуре список однотипных элементов: строки документа, перечень товаров, массив контрагентов. В терминах XDTO такой список — это свойство объекта, у которого в схеме задано множественное вхождение.
Главная сложность для начинающих разработчиков в том, что список XDTO нельзя просто заполнить присваиванием, как обычный массив. Сначала нужно получить сам объект списка через свойство владельца, а затем добавлять в него элементы методом Добавить(). Если попытаться присвоить значение напрямую, платформа выдаст ошибку, потому что свойство списка доступно только для чтения.
Ниже разобран полный цикл работы: от получения типа из фабрики XDTO до проверки результата в итоговом XML. Примеры приведены на встроенном языке 1С и подходят для любой конфигурации на управляемых формах.
Что такое список XDTO и где он описывается
Список в модели XDTO — это свойство объекта, которое может содержать несколько значений одного типа. В XML-схеме (XSD) такое свойство описывается элементом с атрибутом maxOccurs="unbounded" или с конкретным верхним ограничением. Внутри конфигурации 1С списки объявляются в пакетах XDTO, которые добавляются в ветку «XDTO-пакеты» дерева конфигурации.
Когда вы обращаетесь к такому свойству у объекта XDTO, платформа возвращает объект типа СписокXDTO. Это коллекция, похожая по поведению на массив: у неё есть методы Добавить(), Количество(), Получить(), Удалить(), Вставить(). Но в отличие от массива, список XDTO строго типизирован — добавить в него можно только объекты того типа, который задан в схеме.
Подготовка: пакет XDTO и типы данных
Прежде чем создавать список в коде, убедитесь, что в конфигурации есть пакет XDTO с нужной структурой. Откройте конфигуратор, перейдите в раздел «Общие — XDTO-пакеты» и проверьте, что в схеме у нужного объекта есть свойство с множественным вхождением. Если пакета нет, его можно создать вручную через конструктор или импортировать из XSD-файла, предоставленного контрагентом (например, схемой веб-сервиса).
Для примера будем считать, что есть пакет с URI пространства имён "http://example.com/orders", в нём тип Заказ со свойством-списком Товары, а элементы списка имеют тип СтрокаТовара с полями Наименование и Количество. Если имена свойств в вашей схеме на русском или английском — код адаптируется простой заменой идентификаторов.
Пошаговое создание списка XDTO
Базовый алгоритм всегда одинаковый: получаем тип объекта-владельца, создаём объект, обращаемся к свойству-списку и наполняем его. Ниже полный пример кода.
// 1. Получаем тип объекта-владельца из фабрики
ТипЗаказ = ФабрикаXDTO.Тип("http://example.com/orders", "Заказ");
// 2. Создаём объект XDTO
Заказ = ФабрикаXDTO.Создать(ТипЗаказ);
// 3. Заполняем простые свойства
Заказ.Номер = "А-001";
// 4. Обращаемся к свойству-списку и добавляем элементы
ТипСтрока = ФабрикаXDTO.Тип("http://example.com/orders", "СтрокаТовара");
Для Каждого СтрокаТовара Из ТаблицаТоваров Цикл
Элемент = ФабрикаXDTO.Создать(ТипСтрока);
Элемент.Наименование = СтрокаТовара.Наименование;
Элемент.Количество = СтрокаТовара.Количество;
Заказ.Товары.Добавить(Элемент);
КонецЦикла;
Ключевой момент — строка Заказ.Товары.Добавить(Элемент). Свойство Товары возвращает объект СписокXDTO, и именно у него вызывается метод Добавить(). Попытка написать Заказ.Товары = Элемент или присвоить массив приведёт к ошибке «Свойство доступно только для чтения».
- 1Получите тип объекта-владельца через ФабрикаXDTO.Тип(URI, ИмяТипа)
- 2Создайте объект методом ФабрикаXDTO.Создать(Тип)
- 3Получите тип элемента списка из той же схемы
- 4В цикле создавайте элементы через ФабрикаXDTO.Создать() и заполняйте их свойства
- 5Добавляйте каждый элемент методом Список.Добавить(Элемент)
- 6Проверьте объект через ЗаписьXML или выгрузку в строку
Как выгрузить список в XML и проверить результат
После заполнения объект обычно сериализуется в XML — для отправки в веб-сервис или записи в файл. Используется объект ЗаписьXML с установкой соответствия пространств имён фабрики.
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку("UTF-8");
ФабрикаXDTO.ЗаписатьXML(Запись, Заказ);
СтрокаXML = Запись.Закрыть();
Сообщить(СтрокаXML); // для проверки результата
В полученном XML каждый элемент списка должен появиться отдельным тегом: если добавлено три товара, в документе будет три узла Товары внутри узла Заказ. Если узел один, хотя строк было больше — проверяйте, не создаётся ли элемент заново вместо добавления, и не теряется ли ссылка на список между итерациями.
Как проверить результат
Число тегов элемента равно числу добавленных строк
Один узел при нескольких строках или пустой список
Каждый узел содержит свои данные из соответствующей строки
Во всех узлах продублированы данные последней строки
ФабрикаXDTO.Проверить() или запись проходят без исключений
Ошибка несоответствия типа или обязательного свойства
Типичные ошибки при работе со списками XDTO
Наиболее распространённая ошибка — попытка присвоить значение свойству-списку напрямую. Платформа сообщит, что свойство доступно только для чтения, потому что список является служебным объектом, управляемым фабрикой. Правильный путь — только методы Добавить(), Вставить(), Установить().
Вторая частая проблема — создание элемента списка без указания типа или с типом из другого пространства имён. Если URI в вызове ФабрикаXDTO.Тип() не совпадает с URI пакета, платформа выбросит исключение «Тип не определён». Проверяйте пространство имён в свойствах пакета XDTO в конфигураторе — оно чувствительно к регистру и лишним пробелам.
Третья группа ошибок связана с обязательными свойствами элементов. Если в схеме у типа элемента есть обязательные поля (minOccurs="1"), а вы добавили элемент, не заполнив их, ошибка проявится только при записи XML или вызове Проверить(). Поэтому полезно валидировать объект до отправки.
Какую фабрику XDTO использовать
В платформе доступны глобальный объект ФабрикаXDTO и отдельные фабрики, создаваемые из конкретных пакетов. Для типов, описанных в пакетах конфигурации, обычно достаточно глобальной фабрики — она включает все пакеты конфигурации и стандартные системные схемы.
Отдельная фабрика нужна, когда схема загружается динамически — например, из внешнего XSD-файла, который нельзя встраивать в конфигурацию, или когда разные версии одной схемы должны сосуществовать. В этом случае создаётся объект ФабрикаXDTO через конструктор с набором схем, и все вызовы Создать() и Тип() выполняются уже через эту переменную, а не через глобальный объект.
Сравнение вариантов
Подходит для пакетов, добавленных в конфигурацию. Проще код, не требует загрузки схем вручную. Ограничение: нельзя работать со схемами, не вшитыми в конфигурацию.
Подходит для динамических схем из файлов или WSDL. Гибче, но требует загрузки схемы и хранения объекта фабрики между вызовами.
При работе через WS-ссылки типы создаются через прокси-объект. Удобно для веб-сервисов, но привязывает код к конкретному описанию сервиса.
Изменение и удаление элементов списка
Список XDTO поддерживает не только добавление. Метод Количество() возвращает число элементов, Получить(Индекс) — элемент по позиции (нумерация с нуля), Удалить(Элемент) или Удалить(Индекс) — удаление. Для замены значения по позиции используется Установить(Индекс, Элемент).
Практический сценарий: перед повторной отправкой документа нужно очистить список и заполнить его заново. Прямого метода Очистить() у СписокXDTO нет, поэтому удаление выполняется в цикле с конца: пока Количество() больше нуля, удаляется последний элемент. Либо объект-владелец создаётся заново — это проще и надёжнее, если нет необходимости сохранять остальные заполненные свойства.
При отладке удобно выводить список через цикл: Для Каждого Эл Из Заказ.Товары Цикл Сообщить(Эл.Наименование). Это быстрее показывает реальное содержимое, чем просмотр итогового XML, особенно когда документ большой.
Ограничения и риски
Список XDTO строго типизирован: добавить в него произвольное значение (число, строку, массив) нельзя — только объект XDTO соответствующего типа. Если по схеме элемент списка является простым типом (например, строкой), добавление выполняется напрямую значением: Список.Добавить("текст"). Уточняйте в схеме, объектный это список или список простых значений — от этого зависит синтаксис.
При больших объёмах данных (десятки тысяч элементов) учитывайте, что весь объект XDTO и итоговый XML формируются в памяти. Для очень крупных выгрузок рассмотрите потоковую запись через ЗаписьXML без промежуточного построения всего дерева объектов — это снижает потребление памяти на сервере.
Частые вопросы
Можно ли присвоить массив 1С свойству-списку XDTO?
Нет. Свойство-список доступно только для чтения и принимает элементы исключительно через методы Добавить(), Вставить() и Установить(). Массив нужно перебрать в цикле, преобразуя каждое значение в объект XDTO соответствующего типа.
Почему возникает ошибка «Тип не определён» при вызове ФабрикаXDTO.Тип()?
Причины: неверное пространство имён (проверьте URI в свойствах пакета XDTO, включая регистр символов), отсутствие типа с таким именем в схеме или использование глобальной фабрики там, где тип описан в отдельной динамически загруженной фабрике.
Как создать список простых значений, а не объектов?
Если в схеме элемент списка имеет простой тип (string, integer и т.п.), объект создавать не нужно — значение добавляется напрямую: Заказ.Теги.Добавить("срочный"). Платформа сама выполнит приведение к типу элемента.
Как очистить уже заполненный список XDTO?
Метода Очистить() у СписокXDTO нет. Удаляйте элементы в цикле с конца через Удалить() либо пересоздайте объект-владелец через ФабрикаXDTO.Создать() — второй вариант обычно проще и исключает остаточные данные.
Все узлы списка в XML содержат одинаковые данные. Что не так?
Скорее всего, элемент создан один раз вне цикла, а внутри цикла только меняются его свойства и повторно вызывается Добавить(). Создавайте новый объект элемента через ФабрикаXDTO.Создать() на каждой итерации цикла.
Чем список XDTO отличается от ТаблицаЗначений при обмене?
ТаблицаЗначений — внутренняя структура 1С, она не сериализуется в XML напрямую. Список XDTO — часть объектной модели, привязанной к XML-схеме, и автоматически преобразуется в повторяющиеся узлы при записи. Для обмена с внешними системами данные из таблиц переносятся в списки XDTO.
Что важно запомнить
Список XDTO заполняется через свойство объекта-владельца методом Добавить(), каждый элемент создаётся отдельным вызовом ФабрикаXDTO.Создать() внутри цикла. Проверяйте пространство имён, обязательные свойства и итоговый XML — большинство ошибок выявляется именно на этапе валидации.