Как правильно настроить тип значения XDTO, чтобы строки с пробелами не обрезались и не превращались в массив?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с интеграциями через механизмы XDTO (XML Data Transfer Objects) разработчики часто сталкиваются с необходимостью создания собственных типов данных. Это позволяет наложить дополнительные ограничения на данные, такие как длина строки, формат числа или проверка по регулярному выражению. Однако типичной проблемой является ситуация, когда созданный строковый тип начинает вести себя странно: любые переданные значения, содержащие пробелы, «разрезаются» на части, и вместо одной строки 1С возвращает ФиксированныйМассив. Рассмотрим подробнее, почему это происходит и как правильно настроить пакет XDTO для корректной передачи текстовой информации.

Разбор механизмов определения простых типов в XDTO

Для начала проанализируем, как платформа 1С интерпретирует простые типы данных (simple types), основываясь на стандартах XML Schema (XSD). В определении любого типа значения XDTO есть ключевое свойство — Вариант (Variety). Именно от него зависит, как система будет обрабатывать входящую строку. Существует три основных варианта:

  1. Атомарный (Atomic): Значение рассматривается как неделимая единица. Если мы передаем строку "Контора Пишется", она так и останется одной строкой.
  2. Список (List): Значение интерпретируется как последовательность элементов, разделенных пробелами. В этом случае строка "Контора Пишется" превращается в два отдельных значения: "Контора" и "Пишется". В языке 1С это автоматически преобразуется в объект ФиксированныйМассив.
  3. Объединение (Union): Позволяет значению соответствовать одному из нескольких заданных типов (например, либо число, либо строка).

Выясним причину проблемы автора темы: при создании типа MyString в поле «Тип элемента списка» был ошибочно указан базовый тип string. Это автоматически перевело тип в режим «Список». Для решения задачи необходимо использовать поле Базовый тип, оставляя поле «Тип элемента списка» пустым. В этом случае вариант типа станет «Атомарным», и пробелы перестанут быть разделителями.

Настройка фасета whiteSpace (Пробельные символы)

Разберем ситуацию с настройкой фасетов, на которую жаловался автор. Фасет whiteSpace определяет, как именно обработчик XML должен поступать с символами табуляции, возврата каретки и пробелами. Для типа string в стандарте XML предусмотрено три режима:

Посмотрим на ошибки, возникающие при проверке модели: xdto-facet-4.2 Значение 'preserve' фасета 'whitespace' недопустимо для данного типа. Это происходит потому, что в 1С нельзя «расширить» ограничения базового типа. Если вы наследуетесь от типа, который уже имеет ограничение collapse, вы не можете установить ему preserve. Чтобы иметь полный контроль над пробелами, всегда выбирайте в качестве базового типа прямой string (http://www.w3.org/2001/XMLSchema).

Практический пример создания пользовательского типа

Рассмотрим по шагам, как создать тип данных MoneyString, который будет строкой, сохраняющей пробелы, но имеющей ограничение по длине. Это часто требуется для интеграции с системами SAP или Oracle.

  1. Откройте пакет XDTO в конфигураторе.
  2. Перейдите в ветку Типы значений и добавьте новый тип MoneyString.
  3. В свойстве Базовый тип выберите string (http://www.w3.org/2001/XMLSchema).
  4. Убедитесь, что поле Тип элемента списка не заполнено. Свойство Вариант должно отображаться как Атомарный (или быть пустым, что по умолчанию означает атомарность для строк).
  5. В строке Фасеты нажмите кнопку выбора. Установите maxLength (например, 20).

Теперь, если мы будем использовать этот тип в свойствах объектов XDTO, программный код будет работать следующим образом:


// Создание объекта на основании типа из пакета
ТипОбъекта = ФабрикаXDTO.Тип("http://www.uuu.com/sap_1c", "ExitDescription");
НовыйОбъект = ФабрикаXDTO.Создать(ТипОбъекта);

// Запись строки с пробелами
// Если тип настроен как Атомарный, пробелы сохранятся
НовыйОбъект.Exon = "NORMAL OK"; 

// Проверка валидности данных по фасетам (например, по maxLength)
Попытка
    НовыйОбъект.Проверить();
    Сообщить("Данные валидны");
Исключение
    Сообщить("Ошибка проверки: " + ОписаниеОшибки());
КонецПопытки;

Почему данные могут обрезаться при загрузке?

Проанализируем еще один важный момент: автор опасался, что 1С начнет обрезать данные «молча». Важно понимать разницу между моделью данных XDTO и объектами метаданных 1С. Если в XDTO-пакете вы указали длину 10 символов, а в справочнике «Номенклатура» реквизит «Наименование» имеет длину 100 символов, то при чтении XML через ФабрикаXDTO.ПрочитатьXML() вы получите полную строку, если не вызовете метод Проверить(). Обрезка произойдет только в момент записи в реквизит справочника, если его длина в конфигурации меньше, чем длина строки в объекте XDTO.

Для того чтобы сторонние системы (например, SAP) видели ваши ограничения, необходимо выгружать схему пакета в файл .xsd. В этом файле ваши типы будут описаны со всеми фасетами:


<xs:simpleType name="MyString">
    <xs:restriction base="xs:string">
        <xs:whiteSpace value="preserve"/>
        <xs:maxLength value="50"/>
    </xs:restriction>
</xs:simpleType>

Использование системных типов для работы с пробелами

Выясним, когда стоит использовать альтернативные базовые типы вместо ручной настройки фасетов. В пространстве имен http://www.w3.org/2001/XMLSchema уже есть готовые решения:

Рассмотрим пример программной обработки объекта XDTO, где свойство имеет тип token. Даже если вы попытаетесь присвоить ему значение с кучей пробелов, при сериализации они будут обработаны согласно правилам collapse.


// Предположим, свойство Артикул имеет тип xs:token
ОбъектXDTO.Артикул = "  АБ  123  ";
// При выгрузке в XML это превратится в "АБ 123"

Таким образом, для решения проблемы автора достаточно было сменить логику создания типа: Базовый тип вместо Типа элемента списка. Это фундаментальное различие в XDTO, которое определяет, будет ли ваша строка рассматриваться как единый текст или как массив слов.

← На главную