Как правильно типизировать значения и обрабатывать отсутствующие поля при работе с XDTO в 1С?

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

Работа с механизмом XDTO (XML Data Transfer Objects) является стандартом для интеграции современных конфигураций 1С с внешними системами. Однако начинающие разработчики часто сталкиваются с двумя проблемами: необходимостью вручную приводить типы (например, конвертировать строку в число) и обилием конструкций Попытка...Исключение при обращении к необязательным полям XML. Разберем, как оптимизировать эти алгоритмы и сделать код более надежным и производительным.

Автоматическое приведение типов при чтении XML

Часто при чтении XML через ФабрикаXDTO.ПрочитатьXML(ЧтениеXML) разработчик получает объект, где все значения полей представлены в виде строк, даже если в XSD-схеме указано, что это decimal или dateTime. В результате приходится использовать функции вида XMLЗначение(Тип("Число"), ОбъектXDTO.Поле). Это происходит потому, что при «бестиповом» чтении 1С не сопоставляет входящие данные с конкретным описанием из пакета XDTO.

Чтобы 1С автоматически преобразовывала типы данных, необходимо явно указывать тип объекта при вызове метода чтения. Проанализируем правильный подход:


// 1. Получаем тип из фабрики XDTO, используя URI пространства имен и имя типа
ТипОбъекта = ФабрикаXDTO.Тип("http://www.your-company.com/v1/stock", "Stock");

// 2. Читаем XML, передавая вторым параметром ожидаемый тип
// Теперь 1С знает структуру и типы данных из схемы
ОбъектXDTO = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML, ТипОбъекта);

// 3. Обращаемся к свойствам напрямую — они уже имеют правильный тип (Число, Дата и т.д.)
ОбщийОбъем = ОбъектXDTO.volume + 100; // Ошибки не будет, так как volume уже число

При таком подходе 1С выполняет десериализацию в строгом соответствии со схемой. Если в XSD указано xsd:decimal, в свойстве объекта XDTO вы сразу получите тип Число. Это избавляет от лишних преобразований и делает код чище.

Обработка отсутствующих полей без использования Попытки

Вторая распространенная проблема — ошибка «Поле объекта не обнаружено» при обращении к свойствам, которые помечены в схеме как необязательные (minOccurs="0"). Если тег отсутствует в XML-файле, прямое обращение через точку вызывает исключение. Использование Попытка...Исключение существенно замедляет работу системы, особенно при массовой обработке данных.

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

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

Это самый быстрый и «правильный» с точки зрения платформы 1С метод. Он позволяет проверить наличие значения, не вызывая исключений:


// Проверяем, заполнено ли свойство "Part3" в объекте Title
Если ОбъектTitle.ПроверитьУстановлено("Part3") Тогда
    Значение = ОбъектTitle.Part3;
Иначе
    Значение = Неопределено;
КонецЕсли;

Способ 2. Предварительная инициализация типа

Как мы уже выяснили выше, если при чтении XML передать в метод ПрочитатьXML объект типа (ТипОбъектаXDTO), 1С создаст структуру объекта полностью. Для всех отсутствующих в файле свойств, которые описаны в схеме, 1С создаст «заглушки». При обращении к ним через точку вы просто получите Неопределено вместо ошибки. Это позволяет писать лаконичный код без лишних проверок.

Различие между отсутствующим значением и пустым (xsi:nil)

Важно понимать разницу в поведении системы в зависимости от описания в XSD:

  1. Свойство отсутствует (minOccurs="0"): Тега в XML нет. При типизированном чтении значение будет Неопределено.
  2. Свойство пустое (nillable="true"): Тег в XML присутствует, но имеет атрибут xsi:nil="true". В 1С это также вернет Неопределено.
  3. Свойство — пустая строка: Тег выглядит как <tag/> или <tag></tag>. Если тип строковый, вернется пустая строка "".

Использование СериализаторXDTO для конвертации в структуры

Если вам неудобно работать с объектами XDTO напрямую, можно воспользоваться механизмом СериализаторXDTO. Этот подход часто применяется в «Конвертации данных 3.0». Мы можем преобразовать XDTO-объект в привычную 1С-структуру:


// Преобразование XDTO в универсальную коллекцию (структуру или соответствие)
ДанныеСписка = СериализаторXDTO.ПрочитатьXDTO(ОбъектXDTO);

// Теперь можно использовать ЗаполнитьЗначенияСвойств или обращаться к свойствам структуры
// В структуре будут все ключи, соответствующие свойствам XDTO
Если ДанныеСписка.Свойство("Part1") Тогда
    // Работаем с данными
КонецЕсли;

Однако стоит учитывать, что при глубокой вложенности объектов создание структур может быть более ресурсоемким процессом, чем прямая работа с ОбъектXDTO.

Проверка корректности данных (Валидация)

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


Попытка
    ОбъектXDTO.Проверить();
    Сообщить("Объект соответствует схеме XSD");
Исключение
    Сообщить("Ошибка валидации: " + ОписаниеОшибки());
КонецПопытки;

Метод Проверить() автоматически сверяет данные с фасетами схемы (ограничения по длине, регулярные выражения, обязательность заполнения), что значительно сокращает объем кода для проверок.

Выводы и рекомендации

Проанализировав возможности XDTO-фабрики, можно выделить следующие правила хорошего тона при разработке интеграций:

  1. Всегда передавайте Тип в метод ПрочитатьXML. Это обеспечит автоматическую типизацию (числа станут числами, даты — датами) и избавит от ошибок «Поле объекта не обнаружено» для отсутствующих тегов.
  2. Используйте ПроверитьУстановлено(). Это более производительно, чем перехват исключений через Попытка.
  3. Помните про коллекции свойств. Если структура объекта динамическая, вы всегда можете перебрать его свойства через ОбъектXDTO.Тип().Свойства, чтобы понять, какие данные пришли в текущем пакете.
  4. Для больших файлов используйте последовательное чтение. Не читайте огромные XML целиком в XDTO. Используйте ЧтениеXML, чтобы найти нужный узел, и только его превращайте в ОбъектXDTO.
← На главную