При интеграции систем часто возникает ситуация, когда входящий XML-файл не содержит всех полей, описанных в пакете XDTO. По умолчанию платформа 1С:Предприятие выполняет строгую проверку соответствия данных схеме. Если в определении типа свойство помечено как обязательное, а в XML-файле оно отсутствует, метод ПрочитатьXML генерирует исключение. Разберем детально, как обойти это ограничение и успешно загрузить данные.
Прежде всего, проанализируем ситуацию: почему 1С выдает ошибку вида «Не установлено значение одного из следующих свойств». Это происходит потому, что в пакете XDTO для конкретного свойства параметр Минимальное количество (MinOccurs) по умолчанию равен 1. Это означает, что XML-документ считается валидным только в том случае, если этот узел присутствует. Когда механизм ФабрикаXDTO сопоставляет структуру файла со схемой, отсутствие тега расценивается как нарушение целостности данных.
Это наиболее правильный и «чистый» подход с точки зрения архитектуры. Если мы знаем, что некоторые поля могут приходить, а могут и нет, нам необходимо отразить это в самой схеме. Рассмотрим шаги по настройке:
paymentPurpose).<paymentPurpose />), следует установить этот флаг в значение Истина.Многие разработчики опасаются, что установка Минимальное количество = 0 превратит свойство в список (массив). Важно понимать: свойство становится списком только в том случае, если Максимальное количество установлено больше 1 или в значение -1 (неограниченно). Если максимум равен 1, свойство останется одиночным значением, которое может принимать Неопределено при отсутствии данных.
Если у нас нет возможности или желания менять схему XDTO-пакета, мы можем воспользоваться «ленивым» чтением через глобальную фабрику. Разберем, как это работает на примере кода:
// Вместо указания конкретного типа пакета
ТипОбъекта = ФабрикаXDTO.Тип("http://www.ecos-accounting-exchange.org", "PaymentOrder");
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
// Читаем без передачи типа во второй параметр
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
Проанализируем этот подход. Когда мы не передаем тип объекта в метод ПрочитатьXML, 1С пытается создать структуру на лету. Если пространство имен в XML совпадает с каким-то пакетом в системе, платформа все равно может применить правила этого пакета. Однако, если вызвать метод через глобальную переменную ФабрикаXDTO без явного указания ожидаемого типа, проверка на обязательность полей зачастую игнорируется или проходит мягче.
Важный нюанс: При таком чтении все данные, не имеющие явного описания типа, могут быть прочитаны как строки. Типизация (даты, числа) может быть утеряна, и вам придется преобразовывать их вручную.
Чтобы избежать аварийного завершения работы программы, мы можем разделить процесс чтения и процесс проверки. Рассмотрим, как программно обработать ошибки:
// Сначала читаем XML как универсальный объект
Попытка
ПрочитанныйОбъект = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
// Проверяем объект на соответствие типу программно
СписокОшибок = "";
Если НЕ ПрочитанныйОбъект.Проверить(СписокОшибок) Тогда
Сообщить("Объект содержит ошибки валидации, но мы можем продолжать: " + СписокОшибок);
КонецЕсли;
// Работаем со свойствами, которые есть в наличии
Если ПрочитанныйОбъект.Свойства().Получить("paymentPurpose") <> Неопределено Тогда
Значение = ПрочитанныйОбъект.paymentPurpose;
КонецЕсли;
Исключение
Сообщить("Критическая ошибка чтения: " + ОписаниеОшибки());
КонецПопытки;
Использование метода Проверить() позволяет нам получить список всех несоответствий схеме в виде коллекции, не прерывая выполнение кода исключением.
Если структура входящего сообщения крайне нестабильна, мы можем изменить тип проблемного свойства в схеме XDTO на anyType (из пространства имен http://www.w3.org/2001/XMLSchema). Рассмотрим, что это дает:
anyType может содержать любые данные: текст, вложенные объекты или вообще отсутствовать.В ситуациях, когда XDTO-валидация становится непреодолимым препятствием (например, схема защищена или слишком сложна), мы можем использовать ПостроительDOM. Разберем пример реализации:
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ПутьКФайлу);
Построитель = Новый ПостроительDOM;
ДокументDOM = Построитель.Прочитать(ЧтениеXML);
// Получаем узлы по имени напрямую, игнорируя схему
Узлы = ДокументDOM.ПолучитьЭлементыПоИмени("paymentPurpose");
Если Узлы.Количество() > 0 Тогда
Значение = Узлы[0].ТекстовоеСодержимое;
КонецЕсли;
Этот метод работает медленнее, чем XDTO, и требует больше кода для обхода дерева, зато он абсолютно нечувствителен к отсутствующим полям или изменениям в XSD-пакетах.
Выяснив причину ошибки, мы можем выбрать оптимальный путь решения. Если вы контролируете схему XDTO, всегда устанавливайте Минимальное количество = 0 для всех необязательных полей. Это стандарт индустрии. Если схема зафиксирована и не подлежит изменению, используйте чтение через глобальную фабрику без указания типа или предварительную загрузку в дерево DOM для последующего разбора.
Помните, что гибкость при чтении данных повышает отказоустойчивость вашей интеграции, так как внешние системы часто меняются, и жесткая привязка к каждому полю может привести к остановке обмена в самый неподходящий момент.