Как в 1С 7.7 программно проверить XML-файл на соответствие XSD-схеме?

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

Использование системной библиотеки MSXML

Для решения задачи валидации в среде 1С 7.7 задействуем системные COM-объекты Microsoft XML Core Services (MSXML). Процесс проверки строится на взаимодействии двух ключевых объектов:

  1. MSXML2.XMLSchemaCache.6.0 — кэш схем, в который загружается целевой файл XSD.
  2. MSXML2.DOMDocument.6.0 — объектное представление XML-документа, поддерживающее синтаксический анализ и валидацию по прикрепленному кэшу схем.

Рассмотрим структуру и логику создания функции проверки.

Реализация функции валидации XML по XSD-схеме

Напишем универсальную функцию, которая принимает путь к проверяемому файлу, путь к схеме и количество выводимых сообщений об ошибках. Функция возвращает 1 в случае успешной проверки и 0, если обнаружены расхождения со схемой или синтаксические ошибки.


Функция ВалидацияХМЛпоСхеме(ИмяФайла, ИмяСхемы, КолвоВыводимыхОшибок = 1)
    Попытка
        Схема = СоздатьОбъект("MSXML2.XMLSchemaCache.6.0");
    Исключение
        Сообщить("Не удалось создать объект XMLSchemaCache", "!");
        Возврат 0;
    КонецПопытки;
    
    Попытка
        Схема.add("", ИмяСхемы);
    Исключение
        Сообщить("Не удалось подключить схему: " + ИмяСхемы, "!");
        Возврат 0;
    КонецПопытки;
    
    Попытка
        ДОМ = СоздатьОбъект("MSXML2.DOMDocument.6.0");
    Исключение
        Сообщить("Не удалось создать объект DOMDocument", "!");
        Возврат 0;
    КонецПопытки;
    
    ДОМ.schemas = Схема;
    ДОМ.async = 0;
    ДОМ.validateOnParse = -1;
    ДОМ.resolveExternals = -1;
    
    Если (КолвоВыводимыхОшибок > 1) Тогда
        ДОМ.SetProperty("MultipleErrorMessages", -1);
    КонецЕсли;
    
    ДОМ.load(ИмяФайла);
    
    Если (ДОМ.parseError.errorCode <> 0) Тогда
        ВывестиСообщение("При проверке по схеме файла " + ИмяФайла + " выявлены ошибки!", 0);
        Если (КолвоВыводимыхОшибок > 1) Тогда
            Для НомОш = 0 По ДОМ.parseError.allErrors.length - 1 Цикл
                parseError = ДОМ.parseError.allErrors.item(НомОш);
                ВывестиОшибкуРазбораХМЛ(parseError);
                Если НомОш >= КолвоВыводимыхОшибок Тогда
                    ВывестиСообщение("...и еще " + (ДОМ.parseError.allErrors.length - 1 - НомОш) + " ошибок", 0);
                    Прервать;
                КонецЕсли;
            КонецЦикла;
        Иначе
            ВывестиОшибкуРазбораХМЛ(ДОМ.parseError);
        КонецЕсли;
        Возврат 0;
    КонецЕсли;
    
    ДОМ = "";
    Возврат 1;
КонецФункции

Детализация и вывод сообщений об ошибках

Для того чтобы разработчик или пользователь мог оперативно исправить структуру выгрузки, необходимо получить полную информацию о месте возникновения проблемы. Объект parseError предоставляет номер строки, позицию символа, смещение и текстовое описание ошибки.


Процедура ВывестиОшибкуРазбораХМЛ(Ошибка)
    ВывестиСообщение("", 0);
    ВывестиСообщение("Обнаружена ошибка:", 0);
    ВывестиСообщение("Смещение = " + Ошибка.filepos + ", строка = " + Ошибка.line + ", позиция = " + Ошибка.linepos + ", код ошибки = " + Ошибка.errorCode, 0);
    ВывестиСообщение("Описание ошибки: " + Ошибка.reason, 0);
КонецПроцедуры

Функция ФорматироватьТекстСообщения(ТекстСообщения)
    Возврат "" + ТекущаяДата() + " " + ТекущееВремя() + ": " + ТекстСообщения + РазделительСтрок;
КонецФункции

Процедура ВывестиСообщение(Сообщ, Куда = 1, Форматировать = 0)
    Если (Форматировать = 1) Тогда
        ТекСообщ = ФорматироватьТекстСообщения(Сообщ);
    Иначе
        ТекСообщ = Сообщ;
    КонецЕсли;
    
    Если (Куда = 0) ИЛИ (Куда = 2) Тогда
        Сообщить(ТекСообщ, "!");
    КонецЕсли;
    
    Если (Куда = 1) ИЛИ (Куда = 2) Тогда
        Протокол = Протокол + ТекСообщ;
    КонецЕсли;
КонецПроцедуры

Пример вызова проверки после выгрузки документа

Проанализируем практический сценарий интеграции проверки в процедуру формирования электронного документа:


ПолноеИмяФайла = локПапкаОбмена + ИмяФайлаОбмена + ".xml";
ТекстВыгрузкиДанных.Записать(ПолноеИмяФайла);
Сообщить("" + ВыбДокумент + ", " + ВыбДокумент.Контрагент, "i");
Сообщить("успешно выгружен в " + ПолноеИмяФайла, "i");

ИмяСхемы = КаталогИБ() + "XSD.DIR\ON_SFAKT_1_897_01_05_01_01.xsd";
Если ФС.СуществуетФайл(ИмяСхемы) = 0 Тогда
    Сообщить("Внимание: отсутствует формальная схема эл.счета-фактуры, проверка файла не выполняется...", "!");
    Возврат;
КонецЕсли;

Результат = ВалидацияХМЛпоСхеме(ПолноеИмяФайла, ИмяСхемы, 10);
Если Результат <> 0 Тогда
    Сообщить("Информация: сформированный файл обмена успешно прошел проверку на соответствие формальной схеме...", "i");
Иначе
    Сообщить("Ошибка: сформированный файл обмена НЕ ПРОШЕЛ проверку на соответствие формальной схеме, есть ошибки...", "!");
КонецЕсли;

Тонкости и возможные проблемы при валидации

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

  1. Пространства имен (Namespace): метод Схема.add(TargetNamespace, ИмяСхемы) принимает первым параметром URI пространства имен. Если в схеме XSD объявлен атрибут targetNamespace, его значение должно в точности совпадать с переданным параметром. Если пространство имен отсутствует, передается пустая строка "".
  2. Связанные и импортируемые схемы: если в XSD используются конструкции xs:import или xs:include, все вспомогательные схемы должны находиться в том же каталоге или по указанным относительным путям, а свойство ДОМ.resolveExternals обязательно должно быть установлено в -1 (True).
  3. Кодировки и BOM: если XML-файл формируется через объект Текст, он сохраняется в кодировке Windows-1251 (ANSI). Убедимся, что заголовок XML содержит encoding="windows-1251". Несоответствие фактической кодировки файла декларации в заголовке приведет к ошибке разбора еще до этапа проверки по XSD.
  4. Объем памяти: парсер DOM загружает дерево документа в оперативную память целиком. Для файлов размером в сотни мегабайт 32-битный процесс 1С 7.7 может столкнуться с нехваткой памяти. В таких случаях альтернативой выступает вызов внешних консольных утилит (например, xmllint) или потоковая проверка через собственную .NET-компоненту.
  5. Бизнес-логика операторов: важно помнить, что успешная валидация по XSD подтверждает только синтаксическую и структурную корректность документа. Логические проверки (контроль контрольных сумм, актуальность сертификатов, проверка реквизитов по внешним базам) выполняются на стороне оператора ЭДО или принимающей системы отдельно.
← На главную