При интеграции 1С с внешними сайтами, CRM-системами или веб-сервисами разработчики часто сталкиваются с жесткими требованиями к структуре принимаемого XML. Стандартные пакеты обмена (например, CommerceML) используют строго структурированный формат, где списки объектов всегда обернуты в промежуточные теги. Однако многие веб-ресурсы требуют более простой, "плоский" вид данных.
В этой статье мы подробно разберем, как изменить структуру XDTO-пакета в конфигураторе 1С, чтобы вместо вложенной структуры с промежуточными тегами получить линейный список элементов внутри родительского контейнера. Мы также научимся правильно заполнять такую структуру в коде 1С и разберем типичные ошибки, которые могут возникнуть при настройке.
По умолчанию при выгрузке списков (например, товаров или их кодов) платформа 1С генерирует вложенную XML-структуру:
<Products>
<Product>
<Code>7b370a43-35ca-11e9-810c-704d7b85cadd</Code>
</Product>
<Product>
<Code>2ee45d3d-35cb-11e9-810c-704d7b85cadd</Code>
</Product>
</Products>
Здесь тег Products выступает в роли общей коллекции, тег Product обозначает отдельный объект-строку, а тег Code — конкретное свойство этого объекта. Наша задача — избавиться от промежуточного тега Product и получить линейный массив простых значений напрямую внутри родительского тега:
<Products>
<Code>7b370a43-35ca-11e9-810c-704d7b85cadd</Code>
<Code>2ee45d3d-35cb-11e9-810c-704d7b85cadd</Code>
</Products>
Давайте пошагово разберем, как настроить XDTO-пакет для достижения этого результата.
Чтобы платформа 1С поняла, что внутри тега-контейнера должны находиться не сложные объекты, а повторяющиеся простые значения, нам нужно правильно настроить свойства типа объекта XDTO.
ProductsType.Code.string из пространства имен XML-схемы (http://www.w3.org/2001/XMLSchema). Важно: не выбирайте здесь другой объект XDTO, тип должен быть строго простым (типом значения)!0 (если список может быть пустым) или 1 (если в списке должен быть как минимум один элемент).-1. В терминологии XDTO значение -1 означает "неограниченно". Именно этот параметр указывает платформе 1С, что данное свойство является списком (массивом).Благодаря этой настройке 1С будет интерпретировать свойство Code как массив простых строк и при сериализации запишет их в XML одну за другой.
Как правило, список Products не отправляется сам по себе, а находится внутри более крупного документа — "обложки" (например, каталога, заказа или справочника). Выясним, как правильно связать наш новый тип с родительским объектом.
CatalogType или OrderType).Products.ProductsType.Минимальное количество = 1 и Максимальное количество = 1 (так как сам контейнер Products у нас один, а вот коды внутри него будут повторяться).После этой настройки итоговая структура XML примет следующий, требуемый интеграцией вид:
<Catalog>
<Products>
<Code>7b370a43-35ca-11e9-810c-704d7b85cadd</Code>
<Code>2ee45d3d-35cb-11e9-810c-704d7b85cadd</Code>
</Products>
</Catalog>
Работа со свойствами-списками простых типов в коде 1С отличается от работы с обычными объектами XDTO. Поскольку элементами списка являются простые строки, нам не нужно генерировать промежуточные объекты через ФабрикаXDTO.Создать(). Мы должны получить сам список и напрямую добавлять в него строковые значения.
Проанализируем пример кода на встроенном языке 1С:
// 1. Создаем родительский объект (например, Каталог)
КаталогОбъект = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("http://www.yourspace.org/cml", "CatalogType"));
// 2. Создаем объект-контейнер для списка товаров
ТоварыОбъект = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("http://www.yourspace.org/cml", "ProductsType"));
// 3. Связываем родительский каталог с созданным контейнером
КаталогОбъект.Products = ТоварыОбъект;
// 4. Получаем список кодов с помощью метода ПолучитьСписок()
// Этот метод обязателен для работы со свойствами, у которых МаксимальноеКоличество = -1
СписокКодов = ТоварыОбъект.ПолучитьСписок("Code");
// 5. Заполняем список кодов простыми строковыми значениями напрямую
СписокКодов.Добавить("7b370a43-35ca-11e9-810c-704d7b85cadd");
СписокКодов.Добавить("2ee45d3d-35cb-11e9-810c-704d7b85cadd");
СписокКодов.Добавить("aec43a0d-35cb-11e9-810c-704d7b85cadd");
Обратите внимание: если попытаться присвоить значение напрямую через свойство (например, написать ТоварыОбъект.Code = "строка"), платформа выдаст ошибку времени выполнения, поскольку свойство-список ожидает работу через специальный метод ПолучитьСписок().
При настройке XDTO-пакетов начинающие разработчики часто путают два принципиально разных механизма работы со списками:
<Code>Значение1</Code><Code>Значение2</Code>.Code (оставив его максимальное количество равным 1), то на выходе вы получите один-единственный тег, в котором все значения склеятся через пробел:
<Code>7b370a43 2ee45d3d aec43a0d</Code>
Такой формат обычно не принимается внешними системами для передачи идентификаторов, поэтому обязательно следите, чтобы списочным было именно Свойство (через свойство Максимальное количество = -1), а не сам Тип.
В кругах веб-разработчиков и системных архитекторов часто возникают споры о правильности (или "кошерности") плоских списков без промежуточных объектных оберток.
С точки зрения классического проектирования XML-схем (XSD), первый вариант (с вложенным тегом Product) считается правильным и масштабируемым. Объект "Товар" — это сущность. Даже если сейчас вы передаете только его код, в будущем вам может потребоваться передавать наименование, цену или остаток. Наличие промежуточного тега <Product> позволяет легко добавить новые свойства внутрь объекта без изменения логики чтения структуры внешним парсером.
Линейный вариант <Products><Code>...</Code></Products> лишает сущность объектной модели, превращая список товаров в плоский массив строк. Однако для простых интеграций, REST API или систем с дефицитом трафика этот вариант выбирается осознанно, так как он сокращает размер XML-файла и упрощает разбор данных на стороне принимающего скрипта сайта.
Мы успешно решили поставленную задачу, изменили структуру XDTO-пакета в конфигураторе 1С под требования принимающего сайта и научились правильно инициализировать и заполнять списки простых типов в программном коде 1С.