Как проверить значение на соответствие простому типу (SimpleType) и его фасетам из XSD-схемы в 1С?

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

При интеграции систем или формировании XML-файлов по строгим государственным или корпоративным форматам мы часто сталкиваемся с XSD-схемами. В этих схемах для проверки корректности данных используются так называемые простые типы (simpleType). Они накладывают жесткие ограничения на текстовые поля (длина, диапазон значений, соответствие регулярному выражению — паттерну) с помощью механизма фасетов (facets).

В этой статье мы подробно разберем, как заставить платформу 1С проверять текстовые значения на соответствие ограничениям simpleType из XSD-схемы. Мы рассмотрим как классический способ с добавлением схемы в метаданные конфигурации, так и динамические способы работы «на лету» без изменения метаданных.

В чем заключается сложность?

Если мы просто создаем объект XDTO и напрямую присваиваем свойству обычную строку (например, через Свойство = "Значение" или с помощью метода Установить()), 1С часто неявно приводит это свойство к базовому типу Строка (типа xs:string). При этом все специфические ограничения типа, заданные в XSD-схеме (например, ограничение длины или паттерн регулярного выражения), игнорируются, а метод Проверить() не выявляет ошибок валидации. Нам же требуется выполнить полноценную валидацию значения на основе конкретного типа simpleType.

Рассмотрим несколько способов решения этой задачи.

---

Способ 1. Использование статического пакета XDTO (через метаданные конфигурации)

Рассмотрим сценарий, когда схема XSD у нас статична и мы можем добавить ее непосредственно в конфигурацию в качестве Пакета XDTO. Это наиболее быстрый способ, если схема меняется редко.

Выполним следующие шаги для настройки:

  1. Откроем дерево метаданных конфигурации 1С.
  2. Перейдем в ветку Общие -> Пакеты XDTO и добавим новый пакет XDTO.
  3. В свойствах созданного пакета укажем его уникальное URI пространства имен (в соответствии с вашей XSD-схемой).
  4. Перенесем описания simpleType из вашей схемы в созданный пакет XDTO. Это можно сделать путем импорта схемы (через контекстное меню пакета) или переписать нужные типы вручную в свойствах пакета XDTO, задав ограничения (фасеты) — такие как длина, минимальное/максимальное значение и паттерн (регулярное выражение).

После того как типы добавлены в пакет конфигурации, мы можем легко использовать их в коде для валидации данных. Разберем пример кода:


// Получаем нужный тип из системной фабрики XDTO конфигурации
ИмяПространстваИмен = "http://www.sample-tax-service.ru/types"; // URI вашего пакета
ИмяТипаДанных = "typeAddrTotal";

Попытка
    // Получаем объект типа из фабрики XDTO
    ТестТипа = ФабрикаXDTO.Тип(ИмяПространстваИмен, ИмяТипаДанных);
    
    // Проверяемое значение (например, адрес, который должен пройти валидацию по регулярному выражению)
    ПроверяемоеЗначение = "г. Москва, ул. Ленина, д. 10, кв. 15";
    
    // Метод "Проверить" выполняет валидацию значения на соответствие фасетам типа
    ТестТипа.Проверить(ПроверяемоеЗначение);
    
    Сообщить("Успешно! Значение соответствует формату XSD.");
Исключение
    // Метод Проверить() не возвращает Булево. Если значение некорректно, он вызывает исключение.
    Сообщить("Ошибка валидации значения: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

Важное примечание: Метод Проверить() у объекта ТипЗначенияXDTO в случае неуспешной валидации генерирует системное исключение. Поэтому вызов этого метода обязательно нужно оборачивать в конструкцию Попытка ... Исключение.

---

Способ 2. Динамическое создание фабрики XDTO (без изменения метаданных конфигурации)

Что делать, если вносить изменения в конфигурацию нельзя (например, конфигурация находится на поддержке без возможности изменения) или схема XSD загружается из внешнего источника в режиме «1С:Предприятие»? В этом случае мы можем создать фабрику XDTO динамически прямо в коде.

Для этого воспользуемся глобальным методом СоздатьФабрикуXDTO(). Схема работы будет следующей:

  1. Сохраним текст XSD-схемы во временный файл на диске.
  2. Передадим путь к файлу схемы в функцию СоздатьФабрикуXDTO().
  3. Получим из динамически созданной фабрики нужный тип данных и проверим значение.

Давайте реализуем этот алгоритм на практике:


// Шаг 1. Записываем схему из макета конфигурации (или строки) во временный файл
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xsd");

// Предположим, схема хранится в макете двоичных данных "МояСхемаXSD"
ДвоичныеДанныеСхемы = ПолучитьМакет("МояСхемаXSD"); 
ДвоичныеДанныеСхемы.Записать(ИмяВременногоФайла);

// Помещаем путь к временному файлу в массив (метод принимает массив путей к схемам)
МассивФайловСхем = Новый Массив;
МассивФайловСхем.Добавить(ИмяВременногоФайла);

Попытка
    // Шаг 2. Создаем динамическую фабрику XDTO на основе временного файла схемы
    ДинамическаяФабрика = СоздатьФабрикуXDTO(МассивФайловСхем);
    
    // Шаг 3. Получаем тип данных из созданной фабрики
    URIПространстваИмен = "http://www.sample-tax-service.ru/types"; // Пространство имен из XSD
    ИмяТипа = "typeAddrTotal";
    
    ТипИзСхемы = ДинамическаяФабрика.Тип(URIПространстваИмен, ИмяТипа);
    
    // Шаг 4. Проводим валидацию
    ПроверяемаяСтрока = "Недопустимый символ в строке @@@";
    ТипИзСхемы.Проверить(ПроверяемаяСтрока);
    
    Сообщить("Значение успешно прошло валидацию по XSD-схеме!");
Исключение
    Сообщить("Ошибка валидации: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

// Обязательно удаляем временный файл после выполнения операции
Попытка
    УдалитьФайлы(ИмяВременногоФайла);
Исключение
    // Обработка возможных проблем с удалением файла (например, если файл заблокирован процессом)
    ЗаписьЖурналаРегистрации("XDTO.ОчисткаФайлов", УровеньЖурналаРегистрации.Предупреждение,,, "Не удалось удалить файл: " + ИмяВременногоФайла);
КонецПопытки;

---

Способ 3. Создание фабрики XDTO в оперативной памяти (без обращения к жесткому диску)

Иногда запись файлов на жесткий диск сервера нежелательна из-за ограничений прав доступа (например, в некоторых жестко изолированных sandbox-средах или в облачных кластерах). Мы можем полностью исключить дисковые операции, загрузив XSD-схему через объектную модель документов DOM платформы 1С.

Проанализируем пример реализации такого подхода:


// Пусть текст схемы XSD содержится в строковой переменной ТекстXSDСхемы
ТекстXSDСхемы = 
"<xs:schema xmlns:xs=""http://www.w3.org/2001/XMLSchema"" targetNamespace=""http://tempuri.org"" xmlns:tns=""http://tempuri.org"">
|    <xs:simpleType name=""typeAddrTotal"">
|        <xs:restriction base=""xs:string"">
|            <xs:minLength value=""1"" />
|            <xs:maxLength value=""500"" />
|            <xs:pattern value=""[a-zA-Zа-яА-ЯЁё0-9\- \.,'\\/№():_+|""#?!;]*"" />
|        </xs:restriction>
|    </xs:simpleType>
|</xs:schema>";

ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(ТекстXSDСхемы);

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

// Используем ПостроительСхемXML для генерации схемы из структуры DOM
ПостроительСхем = Новый ПостроительСхемXML;
СхемаXML = ПостроительСхем.СоздатьСхемуXML(ДокументDOM);

// Создаем Набор Схем XML и добавляем туда нашу схему
НаборСхем = Новый НаборСхемXML;
НаборСхем.Добавить(СхемаXML);

// Создаем фабрику XDTO непосредственно из набора схем в оперативной памяти
ДинамическаяФабрика = Новый ФабрикаXDTO(НаборСхем);

// Получаем нужный нам простой тип данных
ТипИзПамяти = ДинамическаяФабрика.Тип("http://tempuri.org", "typeAddrTotal");

// Проверяем значение
Попытка
    ПроверяемоеЗначение = "КорректнаяСтрока_123";
    ТипИзПамяти.Проверить(ПроверяемоеЗначение);
    Сообщить("Валидация в памяти успешно пройдена!");
Исключение
    Сообщить("Валидация в памяти провалена: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;

---

Способ 4. Программный обход и извлечение фасетов типа XDTO

Стандартный метод Проверить() выбрасывает системную ошибку 1С, текст которой часто неудобен для конечного пользователя (например: «Ошибка проверки данных XDTO: Значение не соответствует простому типу...»). Если мы хотим вывести пользователю понятное, человекочитаемое сообщение о том, какое именно ограничение было нарушено (например: «Длина текста превышает 500 символов» или «Текст содержит недопустимые спецсимволы»), мы можем программно разобрать коллекцию фасетов типа XDTO.

Рассмотрим, как прочитать фасеты и их значения из типа 1С:


// Получаем доступ к типу данных (из системной или динамической фабрики)
ТестТипа = ФабрикаXDTO.Тип("http://tempuri.org", "typeAddrTotal");

// Перебираем коллекцию фасетов, наложенных на тип данных
Для Каждого Фасет Из ТестТипа.Фасеты Цикл
    
    // Проверяем тип фасета с помощью перечисления ВидФасетаXDTO
    Если Фасет.Вид = ВидФасетаXDTO.Pattern Тогда
        // Регулярное выражение (шаблон)
        Сообщить("Установлен паттерн проверки (Регулярное выражение): " + Фасет.Значение);
        
    ИначеЕсли Фасет.Вид = ВидФасетаXDTO.MinLength Тогда
        // Ограничение минимальной длины строки
        Сообщить("Минимально допустимая длина строки: " + Фасет.Значение);
        
    ИначеЕсли Фасет.Вид = ВидФасетаXDTO.MaxLength Тогда
        // Ограничение максимальной длины строки
        Сообщить("Максимально допустимая длина строки: " + Фасет.Значение);
        
    ИначеЕсли Фасет.Вид = ВидФасетаXDTO.Enumeration Тогда
        // Набор фиксированных значений (Перечисление)
        Сообщить("Допустимое значение из списка: " + Фасет.Значение);
        
    КонецЕсли;
    
КонецЦикла;

Полученные значения фасетов (например, регулярное выражение из фасета Pattern) можно использовать на стороне клиента 1С или передавать в регулярные выражения JavaScript / RegExp платформы для интерактивного контроля ввода пользователя непосредственно в полях формы.

---

Резюме

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

← На главную