Как избавиться от «ОбъектXDTO» при чтении пустых значений XML в 1С?

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

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

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

Почему появляется «ОбъектXDTO» вместо значения?

Для начала проанализируем ситуацию. Когда мы обращаемся к свойству объекта XDTO, 1С пытается вернуть значение в соответствии с описанием типа в схеме (XSD). Если в схеме элемент описан как ComplexType (сложный тип), 1С всегда инициализирует его как объект, даже если в самом XML-файле между тегами ничего нет. Чтобы лучше понимать структуру импортируемых данных, разработчики часто используют инструменты для конвертации схемы XSD в модель XDTO.

Таким образом, обращаясь к ФизЛицо.ИНН, вы получаете не содержимое тега, а сам объект управления этим элементом. Рассмотрим основные причины такого поведения:

  1. Сложный тип данных: Если элемент может содержать вложенные элементы или атрибуты, 1С создает экземпляр ОбъектXDTO. При попытке вывести его в текстовое поле (например, в ячейку таблицы) срабатывает стандартное строковое представление объекта, которое и выглядит как «ОбъектXDTO».
  2. Свойство nillable: В XSD-схемах существует атрибут nillable="true". Если он установлен, а в XML передан атрибут xsi:nil="true", 1С должна возвращать Неопределено. Но если атрибут xsi:nil отсутствует, а тег пуст, создается объект.
  3. Смешанное содержимое (Mixed Content): Если тип элемента позволяет содержать и текст, и вложенные теги, обращение к нему напрямую вернет объект, управляющий последовательностью.

Решение 1: Проверка типа значения (ТипЗнч)

Самый быстрый и практичный способ, часто упоминаемый в практических справочниках разработчика 1С, — это проверка типа полученного значения перед его записью в базу данных. Мы можем проверить, является ли результат объектом XDTO, и если да — заменить его на пустое значение или Неопределено.

Рассмотрим пример кода, который решает эту задачу:


// Предположим, ФизЛицо — это прочитанный объект XDTO
НоваяСтрока = Объект.ТЧ_Данные.Добавить();

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

Используя сокращенную форму записи (тернарный оператор), мы можем сделать код более лаконичным:


НоваяСтрока.Номер = ?(ТипЗнч(ФизЛицо.Номер) = Тип("ОбъектXDTO"), "", ФизЛицо.Номер);

Этот подход надежно защищает ваши реквизиты от записи в них служебной строки «ОбъектXDTO».

Решение 2: Использование метода СвойстваУстановлено()

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

Проанализируем этот подход:


Если ФизЛицо.СвойстваУстановлено("Номер") Тогда
    // Обрабатываем значение, только если оно реально присутствует в XML
    НоваяСтрока.Номер = ФизЛицо.Номер;
Иначе
    НоваяСтрока.Номер = "";
КонецЕсли;

Важный нюанс: Если тег в XML присутствует (например, <Номер></Номер>), метод СвойстваУстановлено вернет Истина, так как узел существует, даже если он пустой. В этом случае проверка типа из первого решения остается более универсальной.

Решение 3: Прямое чтение файла через ЧтениеXML

Если структура XML-файла очень простая или, наоборот, слишком избыточная, использование XDTO может быть неоправданно тяжелым. В таких случаях часто применяется выгрузка и загрузка данных XML с дополнительными опциями, позволяющая более гибко управлять процессом. Рассмотрим альтернативный вариант — использование объекта ЧтениеXML. Как показывают тесты производительности методов чтения XML, этот метод работает быстрее и потребляет меньше памяти, так как не строит дерево объектов.

Разберем пример реализации прямого чтения:


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

Пока Чтение.Прочитать() Цикл
    Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента И Чтение.Имя = "Номер" Тогда
        // Читаем содержимое следующего текстового узла
        Чтение.Прочитать();
        Если Чтение.ТипУзла = ТипУзлаXML.Текст Тогда
            ЗначениеНомера = Чтение.Значение;
        Иначе
            ЗначениеНомера = ""; // Узел пуст
        КонецЕсли;
    КонецЕсли;
КонецЦикла;

В этом случае вы полностью контролируете процесс и гарантированно не получите никаких лишних объектов.

Проблема пустых пространств имен (xmlns="")

В процессе обсуждения была затронута еще одна важная техническая проблема: пространства имен XML и появление атрибута xmlns="" у дочерних элементов при записи XML. Это происходит, когда дочерние элементы «отвязываются» от пространства имен родителя.

Выясним причину: это связано с настройкой elementFormDefault в XSD-схеме.

Если вы создаете объекты программно через Фабрика.Создать(), всегда проверяйте, передаете ли вы правильный ТипОбъектаXDTO, который уже включает в себя нужное пространство имен.

Использование Сериализатора XDTO

Если ваша задача — просто прочитать данные, которые ранее были выгружены из другой базы 1С, наиболее эффективным методом будет Сериализатор XDTO. Аналогичным образом работает адаптивная выгрузка и загрузка данных XML, которая позволяет обмениваться данными даже между не полностью идентичными конфигурациями. Сериализатор автоматически преобразует типы XML в типы 1С (ссылки, числа, даты), корректно обрабатывая пустые значения.

Рассмотрим пример:


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

// Читаем объект целиком, 1С сама превратит пустые теги в пустые строки/ссылки
ОбъектДанных = СериализаторXDTO.ПрочитатьXML(Чтение);

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

Подведем итог: Для быстрого исправления ошибки «ОбъектXDTO» используйте проверку ТипЗнч. Для глубокой и правильной работы с XML контролируйте настройки квалификации элементов в XSD-схемах и используйте методы проверки состояния свойств объекта XDTO.

← На главную