Как в XDTO заполнить только нужные необязательные элементы и исключить пустые теги из XML

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

При работе с интеграциями через XDTO-пакеты разработчики 1С часто сталкиваются с ситуацией, когда XSD-схема содержит множество необязательных полей в рамках одной последовательности xs:sequence. Основная сложность заключается в том, чтобы итоговый XML-файл содержал только те узлы, которые действительно заполнены данными, не включая пустые теги или значения по умолчанию. Рассмотрим подробно, как управлять составом элементов в объекте XDTO, основываясь на правилах работы платформы 1С.

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

Проанализируем пример схемы, представленный в вопросе. Чтобы ускорить проектирование, можно использовать автоматическое формирование XSD-пакета, а сейчас мы видим описание типа, содержащего последовательность элементов:


<xs:element name="purchaseFeatures" minOccurs="0">
<xs:complexType>
<xs:sequence minOccurs="0">
    <xs:element name="isBudgetUnionState" type="xs:boolean" fixed="true" minOccurs="0"></xs:element>
    <xs:element name="contractConclusionOnSt83Ch2" type="xs:boolean" fixed="true" minOccurs="0"></xs:element>
</xs:sequence>
</xs:complexType>
</xs:element>

Здесь критически важными являются два атрибута: minOccurs="0" и fixed="true". Первый означает, что элемент может отсутствовать в XML-документе. Второй жестко фиксирует значение: если тег присутствует, он обязан содержать true. Наша задача — научиться программно определять, какой из этих тегов попадет в выгрузку, а какой будет полностью проигнорирован сериализатором.

Механика состояния свойств объекта XDTO

Разберем, как 1С работает с объектами XDTO "под капотом". Когда мы создаем новый объект через ФабрикаXDTO.Создать(), платформа инициализирует структуру согласно типу. Однако, если свойство помечено как minOccurs="0", оно изначально находится в состоянии "Не установлено".

Рассмотрим важный нюанс: при просмотре объекта XDTO в отладчике мы можем увидеть, что поле типа boolean отображается как Ложь, а числовое поле как 0. Это часто вводит разработчиков в заблуждение. На самом деле, это лишь визуальное представление значения по умолчанию. Пока вы явно не присвоили свойству значение в коде, оно считается отсутствующим для выгрузки.

Решение проблемы: выборочное заполнение

Выясним, как добиться того, чтобы в блоке purchaseFeatures заполнился только один элемент. Это актуально не только для XDTO, но и когда выполняется экспорт любых документов в JSON. Самый простой и правильный способ — просто не обращаться к тому свойству, которое должно отсутствовать.

Посмотрим на пример кода:


// Создаем объект на основании типа из пакета
ТипОсобенности = ФабрикаXDTO.Тип("http://www.example.org/purchase", "purchaseFeatures");
Особенности = ФабрикаXDTO.Создать(ТипОсобенности);

// Заполняем только первый элемент
Особенности.isBudgetUnionState = Истина;

// К свойству contractConclusionOnSt83Ch2 мы не обращаемся. 
// Несмотря на то, что в отладчике оно может выглядеть как "Ложь",
// в итоговый XML оно не попадет, так как minOccurs="0".

Использование метода Вычеркнуть (Unset)

Бывают ситуации, когда объект XDTO заполняется автоматически (например, при чтении из базы или через универсальные механизмы), и нам нужно программно "удалить" уже установленное значение, чтобы тег исчез из XML. Для этого в языке 1С предусмотрен метод Вычеркнуть() (или Unset() в англоязычном варианте).

Проанализируем ситуацию, когда свойство было заполнено по ошибке:


// Допустим, значение было установлено ранее
Особенности.contractConclusionOnSt83Ch2 = Истина;

// Чтобы элемент полностью исчез из XML-структуры:
Особенности.Вычеркнуть("contractConclusionOnSt83Ch2");

После вызова этого метода состояние свойства снова станет "Не установлено". Это гарантирует, что при записи через ЗаписатьXML() данный узел будет пропущен.

Проверка состояния свойства через метод Установлено (IsSet)

Чтобы не гадать, попадет ли элемент в выгрузку, мы можем воспользоваться методом Установлено(). Похожий принцип применяется, когда выполняется проверка на заполненность обязательных полей в структурах данных, что особенно полезно при написании сложных обработок выгрузки.


Если Особенности.Установлено("isBudgetUnionState") Тогда
    Сообщить("Элемент будет присутствовать в XML");
Иначе
    Сообщить("Элемент пропущен");
КонецЕсли;

Важно: Присвоение значения Неопределено не всегда эквивалентно методу Вычеркнуть(). Если в схеме указано nillable="true", установка в Неопределено может привести к генерации тега с атрибутом xsi:nil="true".

Особенности последовательностей (xs:sequence)

Поскольку в нашей схеме используется конструктор xs:sequence, порядок элементов при их физической записи в XML строго определен схемой. Однако в коде 1С вы можете устанавливать свойства в любом порядке. Платформа самостоятельно упорядочит их в соответствии с XSD-пакетом при сериализации. Если вы заполните только второй элемент последовательности, пропустив первый, это не будет ошибкой — 1С просто сформирует XML, начиная сразу со второго тега, так как первый является необязательным.

Резюме по шагам для разработчика

  1. Проверьте схему: убедитесь, что у нужного элемента действительно стоит minOccurs="0".
  2. Минимализм в коде: если элемент не нужен в XML — просто не присваивайте ему никакого значения после создания объекта.
  3. Используйте метод Вычеркнуть(): если нужно гарантированно удалить свойство из уже существующего объекта XDTO.
  4. Не путайте с nillable: помните, что отсутствие тега (minOccurs) и пустой тег с признаком "null" (nillable) — это разные вещи в XML.
  5. Учитывайте fixed: если вы все же решили заполнить элемент, значение должно строго соответствовать тому, что указано в схеме (в данном случае Истина).

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

← На главную