Как создать объект XDTO со значением и атрибутами в 1С

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

При интеграции 1С с внешними системами (например, через EDI или веб-сервисы) разработчики часто сталкиваются со специфической структурой XML-данных. Одной из самых коварных является структура типа simpleContent. Это ситуация, когда XML-элемент должен содержать одновременно и текстовое значение, и атрибуты. Типичный пример: <requestedQuantity unitOfMeasure="PCE">3.000</requestedQuantity>.

Попытка создать такой объект «в лоб» через метод ФабрикаXDTO.Создать() часто приводит к ошибке «Несоответствие типов». В этой статье мы подробно разберем, почему это происходит и как правильно настроить XDTO-пакет и программный код для решения этой задачи.

Анализ проблемы и структуры XSD-схемы

Проанализируем фрагмент XSD-схемы, который вызывает затруднения. В нем определен комплексный тип QuantityType, который расширяет простой тип QuantityValueType (основанный на decimal) и добавляет обязательный атрибут unitOfMeasure. В терминах XSD это выглядит так:


<xsd:complexType name ="QuantityType">
  <xsd:simpleContent>
    <xsd:extension base="QuantityValueType">
      <xsd:attribute name="unitOfMeasure" type="UoMListType" use="required"/>
    </xsd:extension>
  </xsd:simpleContent>
</xsd:complexType>

Когда мы пытаемся выполнить код ФабрикаXDTO.Создать(ТипQuantityType, 4), платформа 1С ожидает, что для комплексного типа будет передан либо объект XDTO, либо структура данных, но не простое число. Однако, если мы создадим объект без значения и попытаемся присвоить атрибут, мы не найдем у объекта свойства, отвечающего за «тело» (содержимое) тега. Выясним, как обойти это ограничение.

Шаг 1: Настройка XDTO-пакета в конфигураторе

Прежде чем писать код, необходимо убедиться, что свойства типа в XDTO-пакете позволяют работать с текстовым содержимым. Это ключевой момент, без которого программные методы не дадут результата. Рассмотрим необходимые настройки:

  1. Откроем XDTO-пакет в конфигураторе.
  2. Найдем нужный ComplexType (в нашем примере QuantityType).
  3. В палитре свойств установим значение Истина для свойства Смешанный (Mixed). Это сообщает платформе, что объект может содержать текстовые данные между тегами.
  4. Установим значение Истина для свойства Последовательный (Ordered). Это позволит управлять порядком элементов и текстового содержимого через специальный объект последовательности.

Важный нюанс: если вы импортируете схему динамически или используете WS-ссылку, убедитесь, что эти свойства корректно интерпретируются платформой. В некоторых случаях может потребоваться ручная корректировка схемы в конфигурации 1С.

Шаг 2: Программная реализация через объект Последовательность

После того как тип настроен как «смешанный», мы получаем возможность записывать данные непосредственно в тело элемента. Рассмотрим правильный алгоритм создания объекта:


// 1. Получаем типы из фабрики
ТипQuantityType = ФабрикаXDTO.Тип("EDIOrder", "QuantityType");

// 2. Создаем объект без передачи значения во второй параметр
ОбъектQuantityType = ФабрикаXDTO.Создать(ТипQuantityType);

// 3. Заполняем атрибуты как обычные свойства объекта
ОбъектQuantityType.unitOfMeasure = "PCE";

// 4. Используем объект последовательности для добавления значения
// Значение добавляется как текст внутрь тега
ОбъектQuantityType.Последовательность().Добавить("4.000");

Разберем подробнее метод Последовательность().Добавить(). Когда свойство Смешанный установлено в Истина, метод Добавить() без указания второго параметра (свойства) вставляет текстовый узел. Именно это значение и окажется внутри тега <requestedQuantity>.

Особенности использования метода Добавить() в последовательности

В зависимости от версии платформы 1С v8.3 и строгости настроек типа, метод Добавить() может вести себя по-разному. Рассмотрим несколько вариантов вызова, если стандартный вариант выдает ошибку:

Вариант с явным указанием Неопределено: Некоторые версии платформы требуют передачи двух параметров. Если вы добавляете текст, второй параметр должен быть Неопределено.

ОбъектQuantityType.Последовательность().Добавить(4, Неопределено);

Вариант с типом данных: Если базовый тип вашего значения — xsd:decimal, старайтесь передавать в метод Добавить() именно число (например, 4), а не строку "4". Платформа самостоятельно выполнит сериализацию в формат XML (с точкой в качестве разделителя), если это предусмотрено типом данных в фабрике.

Почему не работал первоначальный код?

Проанализируем ошибку «Несоответствие типов (параметр номер 2)», с которой столкнулся автор темы. Его код выглядел так:


ЗначениеОбъект = ФабрикаXDTO.Создать(ФабрикаXDTO.Тип("EDIOrder","QuantityValueType"), 4);
ОбъектQuantityType = ФабрикаXDTO.Создать(КлассQuantityType, ЗначениеОбъект); 

Ошибка возникала по двум причинам. Во-первых, QuantityValueType — это simpleType. Результатом ФабрикаXDTO.Создать() для простого типа является не объект XDTO, а обычное значение 1С (в данном случае число 4). Во-вторых, даже если бы это был объект, метод Создать() для комплексного типа при наличии атрибутов не понимает, как «втиснуть» переданный объект в структуру, где ожидаются именованные свойства (атрибуты). Именно поэтому переход к использованию Последовательности является единственным верным архитектурным решением для типов со «смешанным» содержимым.

Резюме для успешной работы

Для корректной работы с simpleContent в XDTO запомним следующие правила:

Соблюдение этого порядка действий позволит вам корректно формировать сложные сообщения для EDI-провайдеров, государственных информационных систем и любых других внешних сервисов, использующих расширенные возможности XML-сериализации.

← На главную