При программном конструировании 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) и назначаем ему имя.ГруппаМоделиXS), которая по умолчанию выступает в роли последовательности <xs:sequence>.ОбъявлениеЭлементаXS), задаем его имя и тип данных через РасширенноеИмяXML.ФрагментXS), в свойство Часть которой помещаем созданное объявление элемента.МинимальноВходит и МаксимальноВходит именно у этого фрагмента.Фрагменты группы модели, а саму группу модели присваиваем свойству Содержимое составного типа.Посмотрим на пример функции на встроенном языке 1С:
&НаСервере
Функция СоздатьСхемуМассиваОбъектныхПрав(СхемаXML, URIПространстваИмен)
ИмяМассива = "ArrayOfObjectRights";
ИмяЭлементаВМассиве = "ObjectRight";
// 1. Создаем составной тип для массива
СхемаМассива = Новый ОпределениеСоставногоТипаXS;
СхемаМассива.Имя = ИмяМассива;
// 2. Создаем контейнер последовательности (xs:sequence)
ГруппаМодели = Новый ГруппаМоделиXS;
// 3. Создаем объявление вложенного элемента
СхемаЭлементаМассива = Новый ОбъявлениеЭлементаXS;
СхемаЭлементаМассива.Имя = ИмяЭлементаВМассиве;
СхемаЭлементаМассива.ИмяТипа = Новый РасширенноеИмяXML(URIПространстваИмен, ИмяЭлементаВМассиве);
// 4. Оборачиваем элемент во ФрагментXS и настраиваем кратность
ФрагментСхемы = Новый ФрагментXS;
ФрагментСхемы.МинимальноВходит = 0;
ФрагментСхемы.МаксимальноВходит = "unbounded";
ФрагментСхемы.Часть = СхемаЭлементаМассива;
// 5. Включаем фрагмент в группу модели
ГруппаМодели.Фрагменты.Добавить(ФрагментСхемы);
// 6. Назначаем группу модели содержимым типа и добавляем в схему
СхемаМассива.Содержимое = ГруппаМодели;
СхемаXML.Содержимое.Добавить(СхемаМассива);
Возврат СхемаМассива;
КонецФункции
Проанализируем важные нюансы, о которых следует помнить при настройке параметров кратности и выгрузке схемы:
МинимальноВходит принимает исключительно целое неотрицательное число (тип Число). Свойство МаксимальноВходит может принимать либо целое неотрицательное число, либо точную строковую константу "unbounded" (в нижнем регистре). Если максимальное количество равно 1, платформа не будет явно выводить атрибут в XML, так как единица является значением по умолчанию.ГруппаМоделиXS свойство Вид установлено в значение ВидГруппыМоделиXS.Все (соответствует тегу <xs:all>), стандарт XML Schema запрещает использование unbounded и чисел больше 1. В такой группе для дочерних фрагментов допустимы только значения 0 или 1.ЗаписьDOM необходимо вызвать метод ОбновитьЭлементDOM() у объекта СхемаXML. Если этот шаг пропустить, результирующий XML-документ схемы окажется пустым.Если работа с объектами модели XS кажется избыточно сложной или требуется гибкое управление текстовым представлением разметки, рассмотрим альтернативные подходы:
СоздатьЭлемент("xs:element"), можно напрямую задать атрибуты вызовами УстановитьАтрибут("minOccurs", "0") и УстановитьАтрибут("maxOccurs", "unbounded"). Это избавит от необходимости строить многослойную цепочку «тип — группа модели — фрагмент — элемент».МинимальноеКоличество = 0 и МаксимальноеКоличество = -1 (значение -1 в XDTO соответствует unbounded). Готовая схема генерируется вызовом метода ФабрикаXDTO.ЭкспортСхемыXML().ЗаписатьНачалоЭлемента, ЗаписатьАтрибут и ЗаписатьКонецЭлемента, минуя тяжеловесные объектные модели.