Как задать minOccurs и maxOccurs для элемента XML-схемы в 1С 8.3?

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

При программном конструировании XML-схем (XSD) с помощью встроенных объектов платформы 1С разработчики часто сталкиваются с неочевидным поведением модели СхемаXML. Типичная задача — сформировать описание массива или списка элементов с ограничениями по количеству вхождений, например:


<xs:complexType name="ArrayOfObjectRights">
    <xs:sequence>
        <xs:element name="ObjectRight" type="tns:ObjectRight" minOccurs="0" maxOccurs="unbounded"/>
    </xs:sequence>
</xs:complexType>

При попытке задать атрибуты напрямую через свойства элемента разработчик обнаруживает, что у объекта ОбъявлениеЭлементаXS попросту отсутствуют свойства для установки минимального и максимального количества вхождений. Если же назначить эти свойства на уровне всего типа, атрибуты попадают не в целевой тег элемента, а на уровень выше — в блок объявления составного типа или последовательности.

Разберем архитектуру компонентной модели XML-схем в 1С, выясним причину такого поведения и рассмотрим правильные варианты реализации задачи.

Архитектурная причина: почему свойства кратности отсутствуют у элемента

Модель типов схемы XML в платформе 1С строго следует спецификации W3C XML Schema Component Model. В синтаксисе XML атрибуты minOccurs и maxOccurs визуально записываются внутри тега <xs:element>. Однако в компонентной модели XSD ограничения кратности принадлежат не самому объявлению элемента (Element Declaration), а промежуточной частице схемы — Particle (в объектной модели 1С это объект ФрагментXS).

Объект ОбъявлениеЭлементаXS представляет собой лишь терминальную часть, которая помещается в свойство Часть объекта ФрагментXS. Именно поэтому свойства МинимальноВходит и МаксимальноВходит доступны только у ФрагментXS. Чтобы получить атрибуты кратности у тега <xs:element>, необходимо корректно выстроить иерархию вложенности объектов.

Решение: программное создание элемента через ФрагментXS

Рассмотрим правильный алгоритм построения составного типа данных, содержащего повторяющийся элемент:

  1. Создаем составной тип (ОпределениеСоставногоТипаXS) и назначаем ему имя.
  2. Создаем группу модели (ГруппаМоделиXS), которая по умолчанию выступает в роли последовательности <xs:sequence>.
  3. Создаем объявление самого элемента (ОбъявлениеЭлементаXS), задаем его имя и тип данных через РасширенноеИмяXML.
  4. Создаем частицу схемы (ФрагментXS), в свойство Часть которой помещаем созданное объявление элемента.
  5. Устанавливаем свойства МинимальноВходит и МаксимальноВходит именно у этого фрагмента.
  6. Добавляем фрагмент в коллекцию Фрагменты группы модели, а саму группу модели присваиваем свойству Содержимое составного типа.

Посмотрим на пример функции на встроенном языке 1С:


&НаСервере
Функция СоздатьСхемуМассиваОбъектныхПрав(СхемаXML, URIПространстваИмен)
    
    ИмяМассива          = "ArrayOfObjectRights";
    ИмяЭлементаВМассиве = "ObjectRight";
    
    // 1. Создаем составной тип для массива
    СхемаМассива = Новый ОпределениеСоставногоТипаXS;
    СхемаМассива.Имя = ИмяМассива;
    
    // 2. Создаем контейнер последовательности (xs:sequence)
    ГруппаМодели = Новый ГруппаМоделиXS;
    
    // 3. Создаем объявление вложенного элемента
    СхемаЭлементаМассива = Новый ОбъявлениеЭлементаXS;
    СхемаЭлементаМассива.Имя     = ИмяЭлементаВМассиве;
    СхемаЭлементаМассива.ИмяТипа = Новый РасширенноеИмяXML(URIПространстваИмен, ИмяЭлементаВМассиве);
    
    // 4. Оборачиваем элемент во ФрагментXS и настраиваем кратность
    ФрагментСхемы = Новый ФрагментXS;
    ФрагментСхемы.МинимальноВходит  = 0;
    ФрагментСхемы.МаксимальноВходит = "unbounded";
    ФрагментСхемы.Часть             = СхемаЭлементаМассива;
    
    // 5. Включаем фрагмент в группу модели
    ГруппаМодели.Фрагменты.Добавить(ФрагментСхемы);
    
    // 6. Назначаем группу модели содержимым типа и добавляем в схему
    СхемаМассива.Содержимое = ГруппаМодели; 
    СхемаXML.Содержимое.Добавить(СхемаМассива);
    
    Возврат СхемаМассива;
    
КонецФункции

Тонкости и ограничения при работе с объектной моделью XS

Проанализируем важные нюансы, о которых следует помнить при настройке параметров кратности и выгрузке схемы:

  1. Формат значений свойств кратности: свойство МинимальноВходит принимает исключительно целое неотрицательное число (тип Число). Свойство МаксимальноВходит может принимать либо целое неотрицательное число, либо точную строковую константу "unbounded" (в нижнем регистре). Если максимальное количество равно 1, платформа не будет явно выводить атрибут в XML, так как единица является значением по умолчанию.
  2. Ограничения групп типа xs:all: если у ГруппаМоделиXS свойство Вид установлено в значение ВидГруппыМоделиXS.Все (соответствует тегу <xs:all>), стандарт XML Schema запрещает использование unbounded и чисел больше 1. В такой группе для дочерних фрагментов допустимы только значения 0 или 1.
  3. Синхронизация с DOM: при формировании схемы программно в оперативной памяти перед ее сериализацией в файл или текстовый поток через ЗаписьDOM необходимо вызвать метод ОбновитьЭлементDOM() у объекта СхемаXML. Если этот шаг пропустить, результирующий XML-документ схемы окажется пустым.

Альтернативные способы формирования схемы

Если работа с объектами модели XS кажется избыточно сложной или требуется гибкое управление текстовым представлением разметки, рассмотрим альтернативные подходы:

  1. Использование объектной модели DOM (ДокументDOM): схему можно сконструировать как обычное XML-дерево. Создавая элемент через метод СоздатьЭлемент("xs:element"), можно напрямую задать атрибуты вызовами УстановитьАтрибут("minOccurs", "0") и УстановитьАтрибут("maxOccurs", "unbounded"). Это избавит от необходимости строить многослойную цепочку «тип — группа модели — фрагмент — элемент».
  2. Экспорт через Фабрику XDTO: структура данных описывается в виде пакета XDTO, где для свойства типа сразу указываются свойства МинимальноеКоличество = 0 и МаксимальноеКоличество = -1 (значение -1 в XDTO соответствует unbounded). Готовая схема генерируется вызовом метода ФабрикаXDTO.ЭкспортСхемыXML().
  3. Потоковая запись через ЗаписьXML: если схема генерируется по строго определенному шаблону или разово, проще и быстрее использовать потоковую запись методами ЗаписатьНачалоЭлемента, ЗаписатьАтрибут и ЗаписатьКонецЭлемента, минуя тяжеловесные объектные модели.
← На главную