При чтении данных из XML-файлов с помощью механизма XDTO разработчики часто сталкиваются с ситуацией, когда необязательный тег отсутствует в исходном файле. Попытка прямого обращения к такому свойству через точку вида ФайлХДТО.Документ.ТегКоторыйМожетОтсутствовать приводит к возникновению исключительной ситуации «Поле агрегатного объекта не обнаружено».
Разберем причины такого поведения платформы 1С:Предприятие и рассмотрим правильные варианты безопасного чтения необязательных реквизитов.
Выясним причину ошибки. Если чтение XML выполняется через метод ФабрикаXDTO.ПрочитатьXML(ЧтениеXML) без явной привязки к заранее зарегистрированной схеме XSD или без передачи типа, фабрика формирует объектную модель динамически «на лету» только на основании тех узлов, которые фактически присутствуют в документе. Если тег в XML отсутствует, соответствующее свойство у созданного экземпляра ОбъектXDTO не создается вовсе.
Даже при наличии описания типа в XSD-схеме (где указан признак minOccurs="0"), для конкретного экземпляра объекта свойство будет считаться неустановленным, и прямое обращение к нему также может вызвать ошибку, если свойство не инициализировано.
Рассмотрим несколько корректных способов решения этой задачи.
Штатным и наиболее лаконичным способом работы с необязательными свойствами в ОбъектXDTO является использование встроенного метода Установлено(). Метод проверяет, задано ли значение свойства в объекте, и возвращает логическое значение (Истина или Ложь).
Посмотрим на пример использования:
ХМЛ = Новый ЧтениеXML();
ХМЛ.ОткрытьФайл(ПутьКФайлу);
ФайлХДТО = ФабрикаXDTO.ПрочитатьXML(ХМЛ);
Если ФайлХДТО.Документ.Установлено("ТегКоторыйМожетОтсутствовать") Тогда
ЗначениеРеквизита = ФайлХДТО.Документ.ТегКоторыйМожетОтсутствовать;
Иначе
ЗначениеРеквизита = Неопределено;
КонецЕсли;
ХМЛ.Закрыть();
Использование метода Установлено() позволяет избежать оборачивания каждой строки в конструкцию Попытка ... Исключение, что делает программный код чистым и легко читаемым.
Если в документе содержится большое количество необязательных реквизитов, постоянное написание условий может загромождать код. В таком случае удобно вынести получение значений в отдельную вспомогательную функцию.
Разберем реализацию функции с проверкой через коллекцию свойств объекта:
Функция ПолучитьСвойствоXDTO(ОбъектXDTO, ИмяСвойства, ЗначениеПоУмолчанию = Неопределено) Экспорт
КоллекцияСвойств = ОбъектXDTO.Свойства();
СвойствоXDTO = КоллекцияСвойств.Получить(ИмяСвойства);
Если СвойствоXDTO = Неопределено Тогда
Возврат ЗначениеПоУмолчанию;
ИначеЕсли НЕ ОбъектXDTO.Установлено(СвойствоXDTO) Тогда
Возврат ЗначениеПоУмолчанию;
Иначе
Возврат ОбъектXDTO.Получить(СвойствоXDTO);
КонецЕсли;
КонецФункции
Теперь обращение к любому реквизиту XML становится безопасным и компактным:
ЗначениеТега = ПолучитьСвойствоXDTO(ФайлХДТО.Документ, "ТегКоторыйМожетОтсутствовать", "");
Проанализируем правильное использование XSD-схем. Создание фабрики на основе XSD само по себе не гарантирует типизацию, если при чтении XML не указан тип считываемого объекта.
Чтобы фабрика применила правила схемы к считываемому файлу, необходимо передавать тип данных вторым параметром метода ПрочитатьXML():
Тип().ПрочитатьXML().Посмотрим на пример чтения с явным указанием типа:
ХМЛ = Новый ЧтениеXML();
ХМЛ.ОткрытьФайл(ПутьКФайлу);
ТипДокумента = МояФабрикаXDTO.Тип("http://v8.1c.ru/edi", "ФайлОбмена");
ФайлХДТО = МояФабрикаXDTO.ПрочитатьXML(ХМЛ, ТипДокумента);
// Если в XSD для свойства задан default, значение подставится автоматически.
// В противном случае проверяем его методом Установлено():
Если ФайлХДТО.Документ.Установлено("ТегКоторыйМожетОтсутствовать") Тогда
ЗначениеРеквизита = ФайлХДТО.Документ.Получить("ТегКоторыйМожетОтсутствовать");
КонецЕсли;
ХМЛ.Закрыть();
Если в схеме XSD для необязательного тега задан атрибут со значением по умолчанию (default="..."), платформа автоматически подставит это значение при обращении к свойству, даже если сам тег отсутствовал в XML-файле.
Подведем итоги:
Установлено() или вспомогательную функцию-обертку.ТипОбъектаXDTO во второй параметр метода ПрочитатьXML().Попытка ... Исключение для проверки наличия тегов крайне не рекомендуется, так как обработка исключений замедляет скорость выполнения алгоритма и усложняет отладку.