При работе с механизмами XDTO в 1С:Предприятии программисты часто сталкиваются с ситуацией, когда вместо ожидаемого текстового значения или числа в реквизит справочника записывается системная строка «ОбъектXDTO». Это происходит потому, что платформа считывает узел XML не как примитивный тип (строку), а как полноценный объект, и при попытке неявного приведения этого объекта к строке выдает его внутреннее представление.
В этой статье мы подробно разберем, почему возникает такая ситуация, как правильно анализировать структуру XDTO и какие методы позволяют извлечь реальные данные из «зашифрованных» узлов.
Разберем ситуацию на примере. Допустим, мы читаем файл XML, где элемент gost описан в схеме (XSD) как тип anyType или как сложный тип ComplexType. Даже если в самом XML этот тег пустой, например <dt:gost/>, или содержит простой текст, 1С создает программный объект типа ОбъектXDTO.
Когда мы пишем код вида СпрОбъект.Гост = productItem.gost;, платформа пытается преобразовать объект в строку. Поскольку ОбъектXDTO — это сложная структура, ее строковым представлением по умолчанию является само название типа. В результате в справочнике мы видим мусорную информацию.
Проанализируем структуру XML. Часто разработчики API передают вспомогательные флаги, которые указывают на наличие или отсутствие данных в соседних тегах. В нашем примере это тег correspondsToGost. Если он равен false, значит, анализировать содержимое gost не имеет смысла.
Рассмотрим пример кода, который позволяет отсечь ненужные данные и избежать записи системной строки:
Если productItem.correspondsToGost = "true" Тогда
// Если флаг Истина, проверяем, не является ли значение системной строкой
Если ЗначениеЗаполнено(productItem.gost) И СокрЛП(productItem.gost) <> "ОбъектXDTO" Тогда
Попытка
// Дополнительно проверяем тип через ТипЗнч
Если ТипЗнч(productItem.gost) = Тип("Строка") Тогда
СпрОбъект.Гост = productItem.gost;
Иначе
// Если это объект, пробуем получить его текстовое содержимое
СпрОбъект.Гост = "";
КонецЕсли;
Исключение
СпрОбъект.Гост = "";
КонецПопытки;
КонецЕсли;
КонецЕсли;
Важное примечание: Если в схеме XDTO поле определено как логическое, сравнение productItem.correspondsToGost = "true" может не сработать, так как значение будет иметь тип Булево. В этом случае следует использовать Если productItem.correspondsToGost = Истина Тогда.
Если тип элемента определен как anyType или тип со смешанным содержимым (mixed), текст внутри тега может не лежать в свойствах объекта напрямую. Для доступа к текстовому блоку в 1С используется свойство Последовательность. Выясним, как программно добраться до текста внутри «пустого» на вид объекта.
Рассмотрим алгоритм получения данных:
// Проверяем, является ли прочитанный элемент объектом XDTO
Если ТипЗнч(productItem.gost) = Тип("ОбъектXDTO") Тогда
ОбъектГOCT = productItem.gost;
// Проверяем наличие последовательности у объекта
Если ОбъектГOCT.Последовательность() <> Неопределено Тогда
Для Индекс = 0 По ОбъектГOCT.Последовательность().Количество() - 1 Цикл
// Извлекаем только текстовые данные
Текст = ОбъектГOCT.Последовательность().ПолучитьТекст(Индекс);
Если ЗначениеЗаполнено(Текст) Тогда
СпрОбъект.Гост = Текст;
Прервать;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Иначе
// Если пришла обычная строка, записываем её напрямую
СпрОбъект.Гост = Строка(productItem.gost);
КонецЕсли;
Существует более универсальный способ «приземлить» типы XDTO на простые типы 1С (Строка, Число, Дата). Для этого воспользуемся глобальным объектом СериализаторXDTO. Он автоматически проанализирует метаданные объекта и попытается вернуть значение в привычном для 1С виде.
Посмотрим на пример реализации:
Попытка
// Метод ПрочитатьXDTO возвращает значение в типе 1С, если это возможно
Значение = СериализаторXDTO.ПрочитатьXDTO(productItem.gost);
Если ТипЗнч(Значение) = Тип("Строка") Тогда
СпрОбъект.Гост = Значение;
Иначе
// Если внутри все равно остался объект, значит данных нет или они сложные
СпрОбъект.Гост = "";
КонецЕсли;
Исключение
СпрОбъект.Гост = "";
КонецПопытки;
Когда мы получаем anyType, мы можем проанализировать сам тип объекта. Если метод productItem.gost.Тип() возвращает определение, в котором нет свойств, но тег в XML выглядит как <gost/>, это означает пустой контейнер. Проанализируем ситуацию программно:
ОбъектXDTO.Свойства().Количество().
Если ТипЗнч(productItem.gost) = Тип("ОбъектXDTO") Тогда
Если productItem.gost.Свойства().Количество() = 0 Тогда
// Это пустой объект, соответствующий тегу <tag/>
СпрОбъект.Гост = "";
Иначе
// Здесь может быть логика обхода вложенных свойств, если они есть
КонецЕсли;
КонецЕсли;
Чтобы ваш код был надежным и не засорял базу данных техническими строками ОбъектXDTO, придерживайтесь следующих правил:
ТипЗнч() перед присваиванием значения реквизиту.ЕстьРеквизитОбъекта() поможет узнать, существует ли свойство у ОбъектXDTO прежде чем обращаться к нему.Строка(ЭлементXDTO) используйте явное извлечение значения через СериализаторXDTO или обращение к текстовой последовательности.anyType там, где ожидаются простые данные (строки или числа).Таким образом, появление текста «ОбъектXDTO» — это не ошибка парсинга, а сигнал о том, что в XML пришла структура вместо значения. Использование одного из предложенных выше методов позволит вам корректно расшифровать данные и обеспечить чистоту информации в вашей системе 1С.