Как расшифровать ОбъектXDTO и избежать появления строки ОбъектXDTO при чтении XML

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

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

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

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

Разберем ситуацию на примере. Допустим, мы читаем файл XML, где элемент gost описан в схеме (XSD) как тип anyType или как сложный тип ComplexType. Даже если в самом XML этот тег пустой, например <dt:gost/>, или содержит простой текст, 1С создает программный объект типа ОбъектXDTO.

Когда мы пишем код вида СпрОбъект.Гост = productItem.gost;, платформа пытается преобразовать объект в строку. Поскольку ОбъектXDTO — это сложная структура, ее строковым представлением по умолчанию является само название типа. В результате в справочнике мы видим мусорную информацию.

Способ 1. Проверка логического флага и фильтрация значения

Проанализируем структуру XML. Часто разработчики API передают вспомогательные флаги, которые указывают на наличие или отсутствие данных в соседних тегах. В нашем примере это тег correspondsToGost. Если он равен false, значит, анализировать содержимое gost не имеет смысла.

Рассмотрим пример кода, который позволяет отсечь ненужные данные и избежать записи системной строки:


Если productItem.correspondsToGost = "true" Тогда
    // Если флаг Истина, проверяем, не является ли значение системной строкой
    Если ЗначениеЗаполнено(productItem.gost) И СокрЛП(productItem.gost) <> "ОбъектXDTO" Тогда 
        Попытка 
            // Дополнительно проверяем тип через ТипЗнч
            Если ТипЗнч(productItem.gost) = Тип("Строка") Тогда
                СпрОбъект.Гост = productItem.gost;
            Иначе
                // Если это объект, пробуем получить его текстовое содержимое
                СпрОбъект.Гост = ""; 
            КонецЕсли;
        Исключение 
            СпрОбъект.Гост = "";    
        КонецПопытки;
    КонецЕсли;
КонецЕсли;

Важное примечание: Если в схеме XDTO поле определено как логическое, сравнение productItem.correspondsToGost = "true" может не сработать, так как значение будет иметь тип Булево. В этом случае следует использовать Если productItem.correspondsToGost = Истина Тогда.

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

Если тип элемента определен как anyType или тип со смешанным содержимым (mixed), текст внутри тега может не лежать в свойствах объекта напрямую. Для доступа к текстовому блоку в 1С используется свойство Последовательность. Выясним, как программно добраться до текста внутри «пустого» на вид объекта.

Рассмотрим алгоритм получения данных:


// Проверяем, является ли прочитанный элемент объектом XDTO
Если ТипЗнч(productItem.gost) = Тип("ОбъектXDTO") Тогда
    ОбъектГOCT = productItem.gost;
    // Проверяем наличие последовательности у объекта
    Если ОбъектГOCT.Последовательность() <> Неопределено Тогда
        Для Индекс = 0 По ОбъектГOCT.Последовательность().Количество() - 1 Цикл
            // Извлекаем только текстовые данные
            Текст = ОбъектГOCT.Последовательность().ПолучитьТекст(Индекс);
            Если ЗначениеЗаполнено(Текст) Тогда
                СпрОбъект.Гост = Текст;
                Прервать;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
Иначе
    // Если пришла обычная строка, записываем её напрямую
    СпрОбъект.Гост = Строка(productItem.gost);
КонецЕсли;

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

Существует более универсальный способ «приземлить» типы XDTO на простые типы 1С (Строка, Число, Дата). Для этого воспользуемся глобальным объектом СериализаторXDTO. Он автоматически проанализирует метаданные объекта и попытается вернуть значение в привычном для 1С виде.

Посмотрим на пример реализации:


Попытка
    // Метод ПрочитатьXDTO возвращает значение в типе 1С, если это возможно
    Значение = СериализаторXDTO.ПрочитатьXDTO(productItem.gost);
    Если ТипЗнч(Значение) = Тип("Строка") Тогда
        СпрОбъект.Гост = Значение;
    Иначе
        // Если внутри все равно остался объект, значит данных нет или они сложные
        СпрОбъект.Гост = "";
    КонецЕсли;
Исключение
    СпрОбъект.Гост = "";
КонецПопытки;

Способ 4. Проверка через метод Тип() и Свойства()

Когда мы получаем anyType, мы можем проанализировать сам тип объекта. Если метод productItem.gost.Тип() возвращает определение, в котором нет свойств, но тег в XML выглядит как <gost/>, это означает пустой контейнер. Проанализируем ситуацию программно:

  1. Проверяем, является ли значение типом ОбъектXDTO.
  2. Если это объект, проверяем количество его свойств через Свойства().Количество().
  3. Если свойств 0 и последовательность пуста — это пустой тег, который нужно игнорировать.

Если ТипЗнч(productItem.gost) = Тип("ОбъектXDTO") Тогда
    Если productItem.gost.Свойства().Количество() = 0 Тогда
        // Это пустой объект, соответствующий тегу <tag/>
        СпрОбъект.Гост = "";
    Иначе
        // Здесь может быть логика обхода вложенных свойств, если они есть
    КонецЕсли;
КонецЕсли;

Рекомендации по корректной обработке XML

Чтобы ваш код был надежным и не засорял базу данных техническими строками ОбъектXDTO, придерживайтесь следующих правил:

Таким образом, появление текста «ОбъектXDTO» — это не ошибка парсинга, а сигнал о том, что в XML пришла структура вместо значения. Использование одного из предложенных выше методов позволит вам корректно расшифровать данные и обеспечить чистоту информации в вашей системе 1С.

← На главную