Почему в XML при выгрузке XDTO в 1С добавляется странный префикс d5p1 и как его убрать?

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

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


<d5p1:Ref xmlns:d5p1="http://v8.1c.ru/8.1/data/enterprise/current-config">95ea1513-cf1d-11e9-851e-bcaec5dbb046</d5p1:Ref>

Попытки жестко переопределить пространство имен по умолчанию с помощью вызова метода ЗаписатьСоответствиеПространстваИмен с пустым префиксом часто игнорируются платформой, и загадочный префикс всё равно возвращается в результирующий файл. В этой статье мы подробно разберем природу этого явления, выясним, откуда берутся такие префиксы, и рассмотрим несколько надежных способов сделать XML-документ чистым и читаемым.

Выясняем причину: откуда берется префикс d5p1?

Для начала проанализируем природу самого префикса. Символы в подобных строках генерируются платформой 1С:Предприятие (а также низкоуровневыми сериализаторами операционной системы) автоматически по строгому шаблону:

d{N}p{M}, где:

  1. d — означает "default" (по умолчанию) или "depth" (глубина вложенности). Это признак того, что префикс был создан автоматически системой, а не задан пользователем вручную.
  2. N — целое число, указывающее на уровень (глубину) вложенности текущего XML-элемента в иерархии документа. Например, цифра 5 означает, что элемент находится на пятом уровне вложенности относительно корня.
  3. p — означает "prefix" (префикс).
  4. M — порядковый номер автогенерируемого пространства имен, которое было обнаружено парсером на этом уровне вложенности.

Платформа прибегает к автогенерации в тот момент, когда сериализатор сталкивается с необходимостью записать объект, принадлежащий определенному пространству имен (например, системному пространству 1С http://v8.1c.ru/8.1/data/enterprise/current-config), но для этого пространства на текущем уровне записи не зарегистрирован понятный ("красивый") префикс.

Почему же не помогает классический метод ЗаписатьСоответствиеПространстваИмен("", "http://v8.1c.ru/8.1/data/enterprise/current-config")? Дело в том, что при использовании стандартных платформенных типов данных, таких как ссылки на справочники CatalogRef или объекты CatalogObject, сериализатор 1С требует обязательного наличия явного, непустого префикса для однозначной идентификации типов. Если вы принудительно пытаетесь связать системное пространство имен с пустым префиксом (сделать его пространством по умолчанию), внутренний механизм сериализации платформы обходит это правило, чтобы избежать потенциальных конфликтов типов в сложных XML-схемах, и генерирует уникальный префикс самостоятельно.

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

Способ 1. Предварительное объявление префиксов в корневом элементе (Рекомендуемый программный метод)

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

Рассмотрим по шагам, как это реализовать на практике. Мы вручную откроем корневой элемент нашего XML-документа, явно сопоставим пространство имен с нашим префиксом, а затем передадим управление фабрике XDTO.

Пример программного кода:


// Создаем объект записи XML и настраиваем параметры
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку(); // Или укажите путь к файлу через ОткрытьФайл()

// Записываем стандартное объявление XML-документа
ЗаписьXML.ЗаписатьОбъявлениеXML();

// Вручную открываем корневой тег нашего XML-сообщения
// Задаем имя корневого элемента и его пространство имен
ЗаписьXML.ЗаписатьНачалоЭлемента("ДанныеОбмена", "http://www.my-company.ru/exchange");

// Самый важный шаг: принудительно регистрируем соответствия пространств имен на уровне корня.
// Теперь платформа будет использовать именно наши префиксы для вложенных типов 1С!
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("v8ent", "http://v8.1c.ru/8.1/data/enterprise/current-config");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xsi", "http://www.w3.org/2001/XMLSchema-instance");
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("xsd", "http://www.w3.org/2001/XMLSchema");

// Выполняем запись нашего XDTO-объекта с помощью фабрики.
// Фабрика "увидит" уже зарегистрированный на верхнем уровне префикс "v8ent" и не станет генерировать "d5p1".
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ВашОбъектXDTO);

// Вручную закрываем корневой элемент документа
ЗаписьXML.ЗаписатьКонецЭлемента();

// Получаем готовый чистый XML-текст
РезультатXML = ЗаписьXML.Закрыть();

При использовании этого метода все вложенные ссылочные типы вместо нечитаемого префикса получат красивый префикс v8ent, который вы жестко определили в коде. Структура XML станет стабильной и предсказуемой.

Способ 2. Отказ от привязки к системным типам 1С (Архитектурно верный подход)

Использование в схемах XDTO системных типов данных платформы, таких как CatalogObject.Организации или CatalogRef.Контрагенты, создает жесткую зависимость вашего файла обмена от внутренних механизмов 1С. Если принимающая сторона — это внешняя веб-служба, мобильное приложение или база данных на другой платформе, им будет сложно валидировать и корректно парсить специфичные пространства имен 1С.

Проанализируем этот момент подробнее. Чтобы полностью избавиться от системных пространств имен и сопутствующих автопрефиксов, рекомендуется проектировать XDTO-пакеты с использованием простых типов данных (строк, чисел, дат):

  1. Откройте ваш XDTO-пакет в конфигураторе.
  2. Для типа объекта (например, "Организация") не выбирайте в качестве базового типа или типа свойства системные объекты 1С.
  3. Опишите все свойства объекта простыми типами из стандартной схемы XML Schema. Например, для уникального идентификатора ссылки используйте тип string из пространства http://www.w3.org/2001/XMLSchema.
  4. При заполнении объекта XDTO перед выгрузкой вручную переносите данные из реквизитов 1С в свойства XDTO-объекта (например, НовыйОбъектXDTO.Ref = Строка(СсылкаНаОбъект.УникальныйИдентификатор());).

Да, этот подход требует написания кода для заполнения каждого свойства вручную и не позволяет просто "сбросить" объект 1С целиком в XDTO. Однако взамен вы получаете абсолютно чистый XML-файл, полностью независимый от платформы 1С, в котором гарантированно не будет никаких автогенерируемых префиксов вроде d5p1.

Способ 3. Программная постобработка готовой XML-строки ("Быстрый" костыль)

Если структура выгрузки простая, объемы данных невелики, а переделывать XDTO-пакет или логику выгрузки нет времени, можно прибегнуть к текстовой замене нежелательных подстрок непосредственно в результирующей XML-строке.

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

Если вы всё же решили применить этот способ, реализуйте его следующим образом:


// Получаем XML-текст из объекта ЗаписьXML
ТекстXML = ЗаписьXML.Закрыть();

// Очищаем XML от объявлений автогенерируемого пространства имен
ТекстXML = СтрЗаменить(ТекстXML, " xmlns:d5p1=""http://v8.1c.ru/8.1/data/enterprise/current-config""", "");

// Удаляем сам префикс у тегов
ТекстXML = СтрЗаменить(ТекстXML, "d5p1:", "");

// Теперь строка содержит "чистые" теги вида <Ref>...</Ref>

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

Стоит ли беспокоиться из-за префиксов d5p1?

В завершение разберем важный теоретический аспект работы с XML. Согласно официальной спецификации консорциума W3C (World Wide Web Consortium), физическое имя префикса в XML-документе не имеет абсолютно никакого значения для принимающих систем и парсеров. Единственное, что действительно важно — это URI пространства имен, на которое этот префикс ссылается.

Любой стандартный XML-парсер (будь то DOM, SAX или встроенные механизмы чтения в других языках программирования) обработает узлы <d5p1:Ref> и <v8ent:Ref> абсолютно одинаково, если оба префикса ведут на один и тот же адрес http://v8.1c.ru/8.1/data/enterprise/current-config.

Реальная необходимость избавляться от автопрефиксов возникает всего в двух случаях:

Мы рекомендуем использовать Способ 1 для сохранения совместимости с типами 1С и красивого визуального оформления XML, либо внедрять Способ 2 для построения надежных, платформенно-независимых интеграций.

← На главную