Как правильно перенести подчиненный справочник через XDTO и решить проблему с полем Owner

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

Перенос данных между различными конфигурациями 1С с использованием механизмов XDTO — задача стандартная, но имеющая свои «подводные камни». Часто программисты сталкиваются с ситуацией, когда обычные справочники переносятся без проблем, а при попытке передать подчиненный справочник (например, Спецификации, подчиненные Номенклатуре) база-приемник выдает ошибку при чтении XML. Рассмотрим подробно, почему это происходит и как правильно сформировать объект XDTO, чтобы поле Owner (Владелец) корректно десериализовалось.

Суть проблемы: почему стандартный код не работает

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


СпецификацияТип = Фабрика.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "CatalogObject.Спецификации");
СпецификацияОбъект = Фабрика.Создать(СпецификацияТип);
СпецификацияОбъект.Code = Выборка.Ссылка.Код;
СпецификацияОбъект.Description = Выборка.Ссылка.Наименование;
// Ошибка закрадывается здесь:
СпецификацияОбъект.Owner = XMLСтрока(Выборка.Владелец); 
СпецификацияОбъект.Ref = XMLСтрока(Выборка.Ссылка);
Фабрика.ЗаписатьXML(ЗаписьХМЛ, СпецификацияОбъект);

При попытке прочитать полученный XML в базе-приемнике через СериализаторXDTO.ПрочитатьXML(ЧтениеХМЛ) возникает ошибка. Проблема заключается в том, что в схеме 1С поле Owner имеет тип ent:AnyRef. Это полиморфный тип, который может содержать ссылку на любой справочник. Когда мы присваиваем этому полю просто строку через XMLСтрока(Выборка.Владелец), фабрика записывает в XML чистый UUID без указания того, к какому типу метаданных он относится.

Выясним причину сбоя: база-приемник получает UUID, но не понимает, в какой таблице искать этого владельца, так как отсутствует атрибут xsi:type. Без него десериализатор не может создать объект ссылки нужного типа.

Решение №1: Принудительная типизация через создание объекта ссылки

Для того чтобы в результирующем XML-файле появился необходимый атрибут xsi:type="CatalogRef.Номенклатура", мы должны передать в свойство Owner не строку, а специальный объект XDTO, представляющий ссылку. Разберем этот процесс по шагам.

  1. Определяем тип ссылки владельца в используемой фабрике.
  2. Создаем экземпляр этого типа, передавая в него строковое представление уникального идентификатора.
  3. Назначаем созданный объект свойству владельца.

Посмотрим на пример исправленного кода:


// Получаем тип ссылки конкретного справочника-владельца из пространства имен enterprise
ТипВладельца = Фабрика.Тип("http://v8.1c.ru/8.1/data/enterprise/current-config", "CatalogRef.Номенклатура");

// Создаем объект ссылки XDTO
ОбъектВладелец = Фабрика.Создать(ТипВладельца, XMLСтрока(Выборка.Владелец));

// Теперь присваиваем свойству Owner не строку, а объект
СпецификацияОбъект.Owner = ОбъектВладелец;

В этом случае при вызове метода Фабрика.ЗаписатьXML система увидит, что тип значения является расширением абстрактного AnyRef, и автоматически добавит в XML-тег Owner описание типа. База-приемник успешно распознает тип и создаст ссылку.

Решение №2: Использование СериализатораXDTO для получения структуры

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

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


// Получаем стандартный XDTO объект ссылки через глобальный сериализатор
СсылкаXDTO = СериализаторXDTO.ВXDTOОбъект(Выборка.Владелец);

// Присваиваем этот объект в поле Owner нашего вручную собираемого справочника
СпецификацияОбъект.Owner = СсылкаXDTO;

Важный момент: этот способ сработает только в том случае, если пространство имен (Namespace) в вашей фабрике совпадает с тем, которое использует СериализаторXDTO (обычно это http://v8.1c.ru/8.1/data/enterprise/current-config).

Разбор структуры XML: как должно быть

Давайте сравним «неправильный» и «правильный» XML, чтобы понимать, чего именно мы добиваемся.

Неправильный XML (ошибка десериализации):

<Owner>d37722b4-6cd9-11e9-93af-8c16454e3d70</Owner>

Здесь десериализатор видит строку, но поле Owner ожидает сложный тип AnyRef. Происходит конфликт типов.

Правильный XML (успешная загрузка):


<Owner xsi:type="v8e:CatalogRef.Номенклатура" xmlns:v8e="http://v8.1c.ru/8.1/data/enterprise/current-config">d37722b4-6cd9-11e9-93af-8c16454e3d70</Owner>

Благодаря атрибуту xsi:type, механизм XDTO точно знает, что данную строку нужно интерпретировать как ссылку на справочник Номенклатура.

Дополнительные рекомендации при работе с XDTO

При разработке сложных обменов рекомендуем придерживаться следующих правил:

Таким образом, мы выяснили, что секрет успешного переноса подчиненных справочников через XDTO заключается в правильной обработке полиморфных полей. Передавая в свойство Owner полноценный объект XDTO вместо строкового UUID, вы обеспечиваете корректную передачу метаинформации о типе ссылки, что позволяет стандартным механизмам 1С беспрепятственно выполнять загрузку данных.

← На главную