Как получить описание (Description/Annotation) и структуру элементов XSD-схемы в 1С?

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

При интеграции с внешними системами и разборе сложных форматов регламентированной отчетности разработчики часто используют механизм XDTO. Создав объект ФабрикаXDTO на основании XSD-схем, можно легко сериализовать и десериализовать XML-документы. Однако при попытке программно исследовать типы фабрики разработчики сталкиваются с проблемой: в объектах ТипОбъектаXDTO и СвойствоXDTO отсутствуют пользовательские описания (теги xs:documentation, xs:annotation, атрибуты Description), а вложенные структуры xs:sequence преобразуются в плоский список свойств.

Разберем причины такого поведения платформы 1С и пошагово реализуем способы извлечения полной структуры и описаний схемы.

Почему Фабрика XDTO не содержит описаний?

Проанализируем назначение механизма XDTO в платформе 1С:Предприятие:

  1. Основная задача фабрики: сериализация, десериализация и валидация данных XML и JSON. Она оптимизирована под скорость работы с данными и строгую типизацию.
  2. Отсечение служебных метаданных: при формировании фабрики из файла XSD все вспомогательные узлы документации (xs:annotation, xs:documentation, xs:appinfo) и комментарии отсекаются платформой. Они не сохраняются в объектах ПакетXDTO или ТипОбъектаXDTO.
  3. Схлопывание композиторов: сложные вложенные блоки группировки (xs:sequence, xs:choice, xs:all) при импорте в фабрику разворачиваются в единый плоский список свойств объекта с сохранением порядка и количественных ограничений (МинимальноеКоличество, МаксимальноеКоличество), но теряют информацию о вложенных секциях.

Таким образом, если перед нами стоит задача не просто передавать данные, но и генерировать интерфейс, строить документацию или выводить подсказки для пользователей на основе XSD, стандартной ФабрикиXDTO недостаточно.

Решение 1: Извлечение метаданных и описаний через DOM-документ

Так как файл XSD представляет собой стандартный XML-документ, для чтения комментариев и блоков xs:documentation используем объектную модель ДокументDOM и объект ПостроительDOM. Это позволяет получить полное дерево схемы со всеми комментариями и аннотациями.

Рассмотрим пример кода для загрузки схемы в DOM и извлечения документации комплексных типов:


Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлуXSD);

Построитель = Новый ПостроительDOM;
ДокументСхемы = Построитель.Прочитать(Чтение);
Чтение.Закрыть();

// Обойдем все дочерние узлы корневого элемента схемы
КорневойЭлемент = ДокументСхемы.ЭлементДокумента;
Для Каждого Узел Из КорневойЭлемент.ДочерниеУзлы Цикл
    Если Узел.ТипУзла = ТипУзлаDOM.Элемент И Узел.ЛокальноеИмя = "complexType" Тогда
        ИмяТипа = Узел.ПолучитьАтрибут("name");
        
        // Ищем вложенный узел аннотации (xs:annotation -> xs:documentation)
        ОписаниеТипа = "";
        Для Каждого Дочерний Из Узел.ДочерниеУзлы Цикл
            Если Дочерний.ТипУзла = ТипУзлаDOM.Элемент И Дочерний.ЛокальноеИмя = "annotation" Тогда
                Для Каждого УзелАннотации Из Дочерний.ДочерниеУзлы Цикл
                    Если УзелАннотации.ТипУзла = ТипУзлаDOM.Элемент И УзелАннотации.ЛокальноеИмя = "documentation" Тогда
                        ОписаниеТипа = СокрЛП(УзелАннотации.ТекстовоеСодержимое);
                    КонецЕсли;
                КонецЦикла;
            КонецЕсли;
        КонецЦикла;
        
        Сообщить(СтрШаблон("Тип: %1 | Описание: %2", ИмяТипа, ОписаниеТипа));
    КонецЕсли;
КонецЦикла;

Решение 2: Комбинированный подход (Фабрика XDTO + карта описаний)

Наиболее удобная архитектурная практика при работе со сложными схемами — объединить возможности валидации через XDTO и метаданные из DOM:

  1. Создаем стандартную фабрику через СоздатьФабрикуXDTO() для работы со структурой типов и значениями.
  2. Параллельно парсим XSD через ПостроительDOM и строим справочную таблицу или Соответствие, где ключом является составное имя вида "URIПространстваИмен#ИмяТипа.ИмяСвойства", а значением — текст описания.
  3. При обходе типов и свойств фабрики обращаемся к сформированной карте и получаем нужный текст описания.

Разберем пример реализации карты описаний:


Функция ПолучитьКартуОписанийСхемы(ПутьКФайлуXSD)
    Карта = Новый Соответствие;
    
    Чтение = Новый ЧтениеXML;
    Чтение.ОткрытьФайл(ПутьКФайлуXSD);
    Построитель = Новый ПостроительDOM;
    Документ = Построитель.Прочитать(Чтение);
    Чтение.Закрыть();
    
    // Получаем все элементы documentation в документе
    СписокДокументаций = Документ.ПолучитьЭлементыПоИмени("xs:documentation");
    Если СписокДокументаций.Количество() = 0 Тогда
        СписокДокументаций = Документ.ПолучитьЭлементыПоИмени("documentation");
    КонецЕсли;
    
    Для Индекс = 0 По СписокДокументаций.Количество() - 1 Цикл
        ЭлементDoc = СписокДокументаций.Получить(Индекс);
        Родитель = ЭлементDoc.РодительскийУзел; // xs:annotation
        
        Если Родитель <> Неопределено И Родитель.РодительскийУзел <> Неопределено Тогда
            ЦелевойЭлемент = Родитель.РодительскийУзел; // complexType или element
            ИмяЦели = ЦелевойЭлемент.ПолучитьАтрибут("name");
            Если ЗначениеЗаполнено(ИмяЦели) Тогда
                Карта.Вставить(ИмяЦели, СокрЛП(ЭлементDoc.ТекстовоеСодержимое));
            КонецЕсли;
        КонецЕсли;
    КонецЦикла;
    
    Возврат Карта;
КонецФункции

Решение 3: Потоковое чтение для объемных XSD-файлов

Если файл схемы имеет большой размер (десятки мегабайт), создание полного дерева DOM может вызвать повышенное потребление оперативной памяти. В этом случае эффективнее применить объект ЧтениеXML в потоковом режиме.

Посмотрим на пример потокового поиска описаний:


Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлуXSD);

ТекущийТип = "";
ВнутриАннотации = Ложь;

Пока Чтение.Прочитать() Цикл
    Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
        Если Чтение.ЛокальноеИмя = "complexType" Или Чтение.ЛокальноеИмя = "element" Тогда
            ТекущийТип = Чтение.ПолучитьАтрибут("name");
        ИначеЕсли Чтение.ЛокальноеИмя = "annotation" Тогда
            ВнутриАннотации = Истина;
        ИначеЕсли Чтение.ЛокальноеИмя = "documentation" И ВнутриАннотации Тогда
            ТекстОписания = Чтение.ПрочитатьТекст();
            Если ЗначениеЗаполнено(ТекущийТип) Тогда
                Сообщить(СтрШаблон("Элемент: %1 -> Описание: %2", ТекущийТип, ТекстОписания));
            КонецЕсли;
        КонецЕсли;
    ИначеЕсли Чтение.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
        Если Чтение.ЛокальноеИмя = "annotation" Тогда
            ВнутриАннотации = Ложь;
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

Чтение.Закрыть();

Решение 4: Исследование структуры схемы через ПостроительСхемXML

Если требуется различать вложенные xs:sequence, xs:choice и группы элементов, которые теряются в фабрике XDTO, можно использовать специализированный объект СхемаXML:


Чтение = Новый ЧтениеXML;
Чтение.ОткрытьФайл(ПутьКФайлуXSD);

ПостроительСхем = Новый ПостроительСхемXML;
Схема = ПостроительСхем.СоздатьСхемуXML(Чтение);
Чтение.Закрыть();

// Объект СхемаXML содержит коллекцию Элементы, Типы, Группы
Для Каждого ЭлементСхемы Из Схема.Элементы Цикл
    // Доступ к модели частиц и композиторов XSD
    Сообщить(СтрШаблон("Имя элемента схемы: %1", ЭлементСхемы.Имя));
КонецЦикла;

Итог: ФабрикаXDTO не предназначена для извлечения описаний и рефлексивного анализа метаданных схемы. Для решения задач выгрузки документации, подсказок или нестандартной структуры используйте ПостроительDOM или потоковое ЧтениеXML параллельно с фабрикой.

← На главную