Как прочитать необязательный тег XML через ФабрикаXDTO в 1С?

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

При чтении данных из XML-файлов с помощью механизма XDTO разработчики часто сталкиваются с ситуацией, когда необязательный тег отсутствует в исходном файле. Попытка прямого обращения к такому свойству через точку вида ФайлХДТО.Документ.ТегКоторыйМожетОтсутствовать приводит к возникновению исключительной ситуации «Поле агрегатного объекта не обнаружено».

Разберем причины такого поведения платформы 1С:Предприятие и рассмотрим правильные варианты безопасного чтения необязательных реквизитов.

Почему возникает ошибка при чтении XML без обязательных тегов

Выясним причину ошибки. Если чтение XML выполняется через метод ФабрикаXDTO.ПрочитатьXML(ЧтениеXML) без явной привязки к заранее зарегистрированной схеме XSD или без передачи типа, фабрика формирует объектную модель динамически «на лету» только на основании тех узлов, которые фактически присутствуют в документе. Если тег в XML отсутствует, соответствующее свойство у созданного экземпляра ОбъектXDTO не создается вовсе.

Даже при наличии описания типа в XSD-схеме (где указан признак minOccurs="0"), для конкретного экземпляра объекта свойство будет считаться неустановленным, и прямое обращение к нему также может вызвать ошибку, если свойство не инициализировано.

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

Способ 1. Проверка наличия значения методом Установлено()

Штатным и наиболее лаконичным способом работы с необязательными свойствами в ОбъектXDTO является использование встроенного метода Установлено(). Метод проверяет, задано ли значение свойства в объекте, и возвращает логическое значение (Истина или Ложь).

Посмотрим на пример использования:


ХМЛ = Новый ЧтениеXML();
ХМЛ.ОткрытьФайл(ПутьКФайлу);

ФайлХДТО = ФабрикаXDTO.ПрочитатьXML(ХМЛ);

Если ФайлХДТО.Документ.Установлено("ТегКоторыйМожетОтсутствовать") Тогда
    ЗначениеРеквизита = ФайлХДТО.Документ.ТегКоторыйМожетОтсутствовать;
Иначе
    ЗначениеРеквизита = Неопределено;
КонецЕсли;

ХМЛ.Закрыть();

Использование метода Установлено() позволяет избежать оборачивания каждой строки в конструкцию Попытка ... Исключение, что делает программный код чистым и легко читаемым.

Способ 2. Использование универсальной функции для чтения свойств

Если в документе содержится большое количество необязательных реквизитов, постоянное написание условий может загромождать код. В таком случае удобно вынести получение значений в отдельную вспомогательную функцию.

Разберем реализацию функции с проверкой через коллекцию свойств объекта:


Функция ПолучитьСвойствоXDTO(ОбъектXDTO, ИмяСвойства, ЗначениеПоУмолчанию = Неопределено) Экспорт

    КоллекцияСвойств = ОбъектXDTO.Свойства();
    СвойствоXDTO = КоллекцияСвойств.Получить(ИмяСвойства);
    
    Если СвойствоXDTO = Неопределено Тогда
        Возврат ЗначениеПоУмолчанию;
    ИначеЕсли НЕ ОбъектXDTO.Установлено(СвойствоXDTO) Тогда
        Возврат ЗначениеПоУмолчанию;
    Иначе
        Возврат ОбъектXDTO.Получить(СвойствоXDTO);
    КонецЕсли;

КонецФункции

Теперь обращение к любому реквизиту XML становится безопасным и компактным:


ЗначениеТега = ПолучитьСвойствоXDTO(ФайлХДТО.Документ, "ТегКоторыйМожетОтсутствовать", "");

Способ 3. Использование фабрики на основе схемы XSD с типом корневого элемента

Проанализируем правильное использование XSD-схем. Создание фабрики на основе XSD само по себе не гарантирует типизацию, если при чтении XML не указан тип считываемого объекта.

Чтобы фабрика применила правила схемы к считываемому файлу, необходимо передавать тип данных вторым параметром метода ПрочитатьXML():

  1. Создаем фабрику XDTO на основе схемы или используем пакет XDTO из состава метаданных конфигурации.
  2. Получаем тип корневого объекта через метод фабрики Тип().
  3. Передаем полученный тип в метод ПрочитатьXML().

Посмотрим на пример чтения с явным указанием типа:


ХМЛ = Новый ЧтениеXML();
ХМЛ.ОткрытьФайл(ПутьКФайлу);

ТипДокумента = МояФабрикаXDTO.Тип("http://v8.1c.ru/edi", "ФайлОбмена");
ФайлХДТО = МояФабрикаXDTO.ПрочитатьXML(ХМЛ, ТипДокумента);

// Если в XSD для свойства задан default, значение подставится автоматически.
// В противном случае проверяем его методом Установлено():
Если ФайлХДТО.Документ.Установлено("ТегКоторыйМожетОтсутствовать") Тогда
    ЗначениеРеквизита = ФайлХДТО.Документ.Получить("ТегКоторыйМожетОтсутствовать");
КонецЕсли;

ХМЛ.Закрыть();

Если в схеме XSD для необязательного тега задан атрибут со значением по умолчанию (default="..."), платформа автоматически подставит это значение при обращении к свойству, даже если сам тег отсутствовал в XML-файле.

Рекомендации по выбору подхода

Подведем итоги:

  1. Для быстрого чтения произвольных или простых XML-файлов без строгой схемы оптимально использовать метод Установлено() или вспомогательную функцию-обертку.
  2. При обработке сложных форматов со множеством вложенных сущностей и необязательных реквизитов рекомендуется сформировать схему XSD и передавать целевой ТипОбъектаXDTO во второй параметр метода ПрочитатьXML().
  3. Использование конструкций Попытка ... Исключение для проверки наличия тегов крайне не рекомендуется, так как обработка исключений замедляет скорость выполнения алгоритма и усложняет отладку.
← На главную