Как изменить или подменить XDTO-пакет с помощью расширения в 1С

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

В процессе разработки и сопровождения систем на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда стандартный XDTO-пакет в типовой конфигурации содержит ошибки или не соответствует актуальным требованиям обмена. Ярким примером является ситуация с форматом EnterpriseData версии 1.6.1, когда в разных релизах «Бухгалтерии предприятия 3.0» содержимое пакета с одним и тем же пространством имен кардинально отличалось. Рассмотрим подробнее, можно ли решить эту задачу с помощью расширений и какие существуют обходные пути.

Ограничения платформы 1С при работе с XDTO в расширениях

Для начала проанализируем, почему стандартный подход «добавить в расширение и изменить» не работает для XDTO-пакетов. В отличие от форм, модулей или некоторых других объектов метаданных, механизм расширений для XDTO-пакетов имеет существенное ограничение:

  1. Приоритет основной конфигурации: Если в основной конфигурации уже существует XDTO-пакет с определенным ПространствомИмен (Target Namespace), то даже если вы добавите пакет с таким же URI в расширение, система при обращении к глобальной фабрике XDTO (через свойство ФабрикаXDTO) будет отдавать предпочтение пакету из основной конфигурации.
  2. Невозможность удаления: Мы не можем «удалить» или «отключить» объект метаданных основной конфигурации внутри расширения.
  3. Конфликты имен: Попытка создать в расширении пакет с тем же именем, что и в основной базе, приведет к ошибке или игнорированию объекта расширения.

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

Способ №1: Создание собственной фабрики XDTO

Поскольку глобальная ФабрикаXDTO инициализируется платформой на основании всех доступных пакетов (с приоритетом основной конфигурации), нам необходимо создать свою локальную фабрику, которая будет содержать «правильный» пакет. Разберем этот процесс по шагам.

Во-первых, добавим в расширение новый XDTO-пакет с исправленной структурой. Чтобы избежать конфликтов, дадим ему уникальное имя, например, EnterpriseData_1_6_1_Исправленный. Пространство имен (URI) можно оставить прежним или изменить — это зависит от того, как реализована логика проверки в коде обмена.

Во-вторых, в коде расширения (через аннотацию &Вместо) нам нужно перехватить момент создания или инициализации фабрики для целей обмена. Проанализируем пример кода, который создает локальную фабрику на основе схем:


// Пример создания локальной фабрики XDTO в расширении
&Вместо("ПолучитьФабрикуXDTOДляОбмена")
Функция Расш1_ПолучитьФабрикуXDTOДляОбмена()
    
    // Получаем схему из нашего исправленного пакета в расширении
    ИсправленныйПакет = Метаданные.XDTOPackets.EnterpriseData_1_6_1_Исправленный;
    
    // Создаем набор схем XML
    НаборСхем = Новый НаборСхемXML;
    // Здесь логика выгрузки схемы пакета в XML
    // ...
    
    // Формируем новую фабрику на основании набора схем
    НоваяФабрика = СоздатьФабрикуXDTO(НаборСхем);
    
    Возврат НоваяФабрика;
КонецФункции

Используя этот метод, мы заставляем подсистему обмена работать не с глобальным контекстом, а с нашей кастомной фабрикой, где структура пакета соответствует нашим требованиям.

Способ №2: Перехват процедур сериализации данных

Если нам нужно исправить работу с форматом EnterpriseData (Универсальный формат обмена), стоит обратить внимание на программные модули, отвечающие за версию формата. Выясним причину ошибки: часто система ищет пакет по его версии или URI.

Рассмотрим перехват в модуле менеджера обмена. Мы можем изменить список доступных версий или подменить логику определения типа. Посмотрим на пример перехвата функции, которая сопоставляет версию формата и пакет:


&Вместо("ОпределитьВерсиюИПространствоИмен")
Процедура Расш1_ОпределитьВерсиюИПространствоИмен(ВерсияФормата, ПространствоИмен)
    // Вызываем оригинальный обработчик
    ПродолжитьВызов(ВерсияФормата, ПространствоИмен);
    
    // Если определилась проблемная версия, подменяем данные
    Если ВерсияФормата = "1.6.1" Тогда
        // Здесь мы можем перенаправить логику на использование 
        // нашего исправленного пакета из расширения
        ПространствоИмен = "http://v8.1c.ru/edi/edi_stnd/EnterpriseData/1.6.1_fixed";
    КонецЕсли;
КонецПроцедуры

Такой подход позволяет оставить основную конфигурацию нетронутой и оперативно внедрить исправления даже в те базы, которые давно не обновлялись.

Способ №3: Хранение схемы XSD в макете

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

Проанализируем алгоритм работы:

  1. Экспортируем правильный XDTO-пакет из исправной конфигурации в файл .xsd.
  2. В расширении создаем макет (тип «Бинарные данные») и загружаем туда этот файл.
  3. В момент выполнения обмена считываем макет и инициализируем фабрику XDTO программно.

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

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

При работе с расширением XDTO-пакетов помните о следующих моментах:

Пространства имен: Будьте осторожны с использованием одинаковых URI. Если код типовой конфигурации использует методы типа ФабрикаXDTO.Тип("http://uri", "ИмяТипа"), он всегда будет обращаться к объекту из основной конфигурации. Единственный способ изменить это поведение — перехватить сам вызов метода и подставить туда объект из вашей локальной фабрики.

Режим совместимости: Возможности расширений сильно зависят от версии платформы. Начиная с версии 8.3.10, работа с метаданными в расширениях стала стабильнее, но фундаментальное ограничение на уникальность URI пространств имен в рамках глобальной фабрики сохраняется и в более поздних версиях (8.3.24+).

Обновление конфигурации: Если проблема вызвана ошибкой релиза (как в случае с БП 3.0.60), самым правильным долгосрочным решением остается обновление до исправленного релиза. Использование расширений для подмены XDTO-пакетов — это мощный, но сложный в поддержке инструмент «быстрого реагирования».

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

← На главную