При интеграции 1С с внешними системами (например, через EDI или веб-сервисы) разработчики часто сталкиваются со специфической структурой XML-данных. Одной из самых коварных является структура типа simpleContent. Это ситуация, когда XML-элемент должен содержать одновременно и текстовое значение, и атрибуты. Типичный пример: <requestedQuantity unitOfMeasure="PCE">3.000</requestedQuantity>.
Попытка создать такой объект «в лоб» через метод ФабрикаXDTO.Создать() часто приводит к ошибке «Несоответствие типов». В этой статье мы подробно разберем, почему это происходит и как правильно настроить XDTO-пакет и программный код для решения этой задачи.
Проанализируем фрагмент 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, либо структура данных, но не простое число. Однако, если мы создадим объект без значения и попытаемся присвоить атрибут, мы не найдем у объекта свойства, отвечающего за «тело» (содержимое) тега. Выясним, как обойти это ограничение.
Прежде чем писать код, необходимо убедиться, что свойства типа в XDTO-пакете позволяют работать с текстовым содержимым. Это ключевой момент, без которого программные методы не дадут результата. Рассмотрим необходимые настройки:
ComplexType (в нашем примере QuantityType).Смешанный (Mixed). Это сообщает платформе, что объект может содержать текстовые данные между тегами.Последовательный (Ordered). Это позволит управлять порядком элементов и текстового содержимого через специальный объект последовательности.Важный нюанс: если вы импортируете схему динамически или используете WS-ссылку, убедитесь, что эти свойства корректно интерпретируются платформой. В некоторых случаях может потребоваться ручная корректировка схемы в конфигурации 1С.
После того как тип настроен как «смешанный», мы получаем возможность записывать данные непосредственно в тело элемента. Рассмотрим правильный алгоритм создания объекта:
// 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 запомним следующие правила:
Смешанный и Последовательный в определении типа в XDTO-пакете.ФабрикаXDTO.Создать(Тип).Объект.ИмяАтрибута = Значение;.Объект.Последовательность().Добавить().Соблюдение этого порядка действий позволит вам корректно формировать сложные сообщения для EDI-провайдеров, государственных информационных систем и любых других внешних сервисов, использующих расширенные возможности XML-сериализации.