При интеграции систем или формировании XML-файлов по строгим государственным или корпоративным форматам мы часто сталкиваемся с XSD-схемами. В этих схемах для проверки корректности данных используются так называемые простые типы (simpleType). Они накладывают жесткие ограничения на текстовые поля (длина, диапазон значений, соответствие регулярному выражению — паттерну) с помощью механизма фасетов (facets).
В этой статье мы подробно разберем, как заставить платформу 1С проверять текстовые значения на соответствие ограничениям simpleType из XSD-схемы. Мы рассмотрим как классический способ с добавлением схемы в метаданные конфигурации, так и динамические способы работы «на лету» без изменения метаданных.
Если мы просто создаем объект XDTO и напрямую присваиваем свойству обычную строку (например, через Свойство = "Значение" или с помощью метода Установить()), 1С часто неявно приводит это свойство к базовому типу Строка (типа xs:string). При этом все специфические ограничения типа, заданные в XSD-схеме (например, ограничение длины или паттерн регулярного выражения), игнорируются, а метод Проверить() не выявляет ошибок валидации. Нам же требуется выполнить полноценную валидацию значения на основе конкретного типа simpleType.
Рассмотрим несколько способов решения этой задачи.
---
Рассмотрим сценарий, когда схема XSD у нас статична и мы можем добавить ее непосредственно в конфигурацию в качестве Пакета XDTO. Это наиболее быстрый способ, если схема меняется редко.
Выполним следующие шаги для настройки:
URI пространства имен (в соответствии с вашей XSD-схемой).simpleType из вашей схемы в созданный пакет XDTO. Это можно сделать путем импорта схемы (через контекстное меню пакета) или переписать нужные типы вручную в свойствах пакета XDTO, задав ограничения (фасеты) — такие как длина, минимальное/максимальное значение и паттерн (регулярное выражение).После того как типы добавлены в пакет конфигурации, мы можем легко использовать их в коде для валидации данных. Разберем пример кода:
// Получаем нужный тип из системной фабрики XDTO конфигурации
ИмяПространстваИмен = "http://www.sample-tax-service.ru/types"; // URI вашего пакета
ИмяТипаДанных = "typeAddrTotal";
Попытка
// Получаем объект типа из фабрики XDTO
ТестТипа = ФабрикаXDTO.Тип(ИмяПространстваИмен, ИмяТипаДанных);
// Проверяемое значение (например, адрес, который должен пройти валидацию по регулярному выражению)
ПроверяемоеЗначение = "г. Москва, ул. Ленина, д. 10, кв. 15";
// Метод "Проверить" выполняет валидацию значения на соответствие фасетам типа
ТестТипа.Проверить(ПроверяемоеЗначение);
Сообщить("Успешно! Значение соответствует формату XSD.");
Исключение
// Метод Проверить() не возвращает Булево. Если значение некорректно, он вызывает исключение.
Сообщить("Ошибка валидации значения: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
Важное примечание: Метод Проверить() у объекта ТипЗначенияXDTO в случае неуспешной валидации генерирует системное исключение. Поэтому вызов этого метода обязательно нужно оборачивать в конструкцию Попытка ... Исключение.
---
Что делать, если вносить изменения в конфигурацию нельзя (например, конфигурация находится на поддержке без возможности изменения) или схема XSD загружается из внешнего источника в режиме «1С:Предприятие»? В этом случае мы можем создать фабрику XDTO динамически прямо в коде.
Для этого воспользуемся глобальным методом СоздатьФабрикуXDTO(). Схема работы будет следующей:
СоздатьФабрикуXDTO().Давайте реализуем этот алгоритм на практике:
// Шаг 1. Записываем схему из макета конфигурации (или строки) во временный файл
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xsd");
// Предположим, схема хранится в макете двоичных данных "МояСхемаXSD"
ДвоичныеДанныеСхемы = ПолучитьМакет("МояСхемаXSD");
ДвоичныеДанныеСхемы.Записать(ИмяВременногоФайла);
// Помещаем путь к временному файлу в массив (метод принимает массив путей к схемам)
МассивФайловСхем = Новый Массив;
МассивФайловСхем.Добавить(ИмяВременногоФайла);
Попытка
// Шаг 2. Создаем динамическую фабрику XDTO на основе временного файла схемы
ДинамическаяФабрика = СоздатьФабрикуXDTO(МассивФайловСхем);
// Шаг 3. Получаем тип данных из созданной фабрики
URIПространстваИмен = "http://www.sample-tax-service.ru/types"; // Пространство имен из XSD
ИмяТипа = "typeAddrTotal";
ТипИзСхемы = ДинамическаяФабрика.Тип(URIПространстваИмен, ИмяТипа);
// Шаг 4. Проводим валидацию
ПроверяемаяСтрока = "Недопустимый символ в строке @@@";
ТипИзСхемы.Проверить(ПроверяемаяСтрока);
Сообщить("Значение успешно прошло валидацию по XSD-схеме!");
Исключение
Сообщить("Ошибка валидации: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
// Обязательно удаляем временный файл после выполнения операции
Попытка
УдалитьФайлы(ИмяВременногоФайла);
Исключение
// Обработка возможных проблем с удалением файла (например, если файл заблокирован процессом)
ЗаписьЖурналаРегистрации("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";
ТипИзПамяти.Проверить(ПроверяемоеЗначение);
Сообщить("Валидация в памяти успешно пройдена!");
Исключение
Сообщить("Валидация в памяти провалена: " + КраткоеПредставлениеОшибки(ИнформацияОбОшибке()));
КонецПопытки;
---
Стандартный метод Проверить() выбрасывает системную ошибку 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 и метода Проверить() — это мощный и быстрый индустриальный стандарт валидации данных, который избавляет разработчиков от необходимости писать сложные велосипеды ручной проверки строк на регулярные выражения и соответствие длине.