Как сгенерировать XML с помощью Фабрики XDTO без пространств имен

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

При работе с интеграциями программисты 1С часто сталкиваются с жестким требованием принимающей стороны: XML-файл не должен содержать объявлений пространств имен (атрибуты xmlns) в корневом теге или вложенных элементах. Однако ФабрикаXDTO, работающая по стандартам XML Schema, по умолчанию всегда добавляет эти данные, так как они являются фундаментом типизации XDTO. В этой статье мы разберем несколько способов, как обойти это ограничение и получить "чистый" XML, сохранив при этом удобство работы с объектами XDTO.

Причина возникновения проблемы

Проанализируем ситуацию: когда мы вызываем метод ФабрикаXDTO.ЗаписатьXML(), система обращается к метаданным пакета XDTO. Если у пакета заполнен атрибут targetNamespace (целевое пространство имен), платформа обязана указать его в результирующем файле, чтобы документ соответствовал схеме. Даже если мы программно создаем объект, он остается привязанным к своему типу внутри пространства имен. Рассмотрим, какие существуют обходные пути, чтобы исключить эти атрибуты из финального текста.

Способ 1. Гибридный метод записи (Ручное управление корнем)

Это наиболее элегантный программный метод. Суть его заключается в том, что мы не отдаем весь объект целиком на откуп фабрике, а берем на себя формирование корневого узла. Выясним, как это реализовать на практике. Мы создаем объект ЗаписьXML, вручную записываем начало элемента без указания URI, а затем используем фабрику только для сериализации вложенного содержимого.

Рассмотрим пример кода:


// Создаем объект записи и параметры
Запись = Новый ЗаписьXML;
ПараметрыЗаписи = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Истина);
Запись.ОткрытьФайл(ПутьКФайлу, ПараметрыЗаписи);
Запись.ЗаписатьОбъявлениеXML();

// Записываем корневой тег вручную БЕЗ пространства имен
Запись.ЗаписатьНачалоЭлемента("RootElementName"); 

// Допустим, ОбъектXDTO — это наш подготовленный объект
// Перебираем все свойства объекта и записываем их через фабрику
Для каждого Свойство Из ОбъектXDTO.Тип().Свойства Цикл
    ЗначениеСвойства = ОбъектXDTO.Получить(Свойство.Имя);
    Если ЗначениеСвойства <> Неопределено Тогда
        // Записываем вложенные элементы, подавляя определение типов
        ФабрикаXDTO.ЗаписатьXML(Запись, ЗначениеСвойства, Свойство.Имя, , , ВариантУзлаXML.Никто);
    КонецЕсли;
КонецЦикла;

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

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

Способ 2. Использование объектной модели документа (DOM)

Если структура XML сложная и гибридный метод реализовать затруднительно, мы можем воспользоваться встроенными механизмами DOM (Document Object Model). Проанализируем этот подход: сначала мы генерируем "грязный" XML в память, затем загружаем его в дерево DOM, программно удаляем ненужные атрибуты и сохраняем результат. Это гораздо надежнее, чем простая замена строк в текстовом редакторе.

Посмотрим на последовательность действий:

  1. Сериализуем объект XDTO в объект ЗаписьXML, который пишет в память (строку).
  2. Создаем ПостроительDOM и читаем полученную строку.
  3. Получаем корневой элемент документа.
  4. Итерируем по коллекции атрибутов и удаляем те, что начинаются на "xmlns".
  5. Записываем очищенный ДокументDOM обратно в файл.

Пример программной реализации:


// 1. Генерируем XML во временную строку
Запись = Новый ЗаписьXML;
Запись.УстановитьСтроку();
ФабрикаXDTO.ЗаписатьXML(Запись, МойОбъектXDTO);
СтрXML = Запись.Закрыть();

// 2. Загружаем в DOM
Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(СтрXML);
ПостроительDOM = Новый ПостроительDOM;
ДокументDOM = ПостроительDOM.Прочитать(Чтение);
Корень = ДокументDOM.ДокументОбъект;

// 3. Очищаем атрибуты (пространства имен)
СписокАтрибутовДляУдаления = Новый Массив;
Для каждого Атрибут Из Корень.Атрибуты Цикл
    Если Найти(Атрибут.Имя, "xmlns") > 0 Тогда
        СписокАтрибутовДляУдаления.Добавить(Атрибут);
    КонецЕсли;
КонецЦикла;

Для каждого Атр Из СписокАтрибутовДляУдаления Цикл
    Корень.УдалитьАтрибутУзла(Атр);
КонецЦикла;

// 4. Сохраняем результат
ЗаписьИтог = Новый ЗаписьXML;
ЗаписьИтог.ОткрытьФайл(ПутьКФайлу);
ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(ДокументDOM, ЗаписьИтог);
ЗаписьИтог.Закрыть();

Способ 3. Настройка свойств элементов «Форма» в пакете XDTO

Если вам мешают префиксы (например, d4p1:Name) внутри самого тела XML, можно изменить настройки самого XDTO-пакета. Разберем, как это влияет на визуальное представление данных. В редакторе пакета у каждого элемента (или у самого пакета для всех вложенных свойств) есть свойство Форма (Form).

Если установить значение Unqualified, платформа перестанет добавлять префиксы пространств имен к дочерним элементам. Это сделает структуру более читаемой. Однако стоит помнить, что это не уберет главное объявление xmlns в корне. Поэтому данный метод обычно используется как вспомогательный вместе с первым или вторым способом.

Способ 4. Программное создание модели XDTO без URI

Существует продвинутый способ: создание типов "на лету" без привязки к конкретному пространству имен. Если использовать объект МодельXDTO и программно описывать типы, не назначая им targetNamespace, то при выгрузке фабрика может не найти URI для сопоставления и выдаст чистые теги. Но этот путь трудозатратен, так как требует ручного описания всей структуры данных в коде вместо использования визуального конструктора.

Резюме и рекомендации

Подведем итог нашему анализу. Выбор метода зависит от ваших ограничений:

Важно помнить, что удаление пространств имен делает XML технически "анонимным", и стандартные валидаторы не смогут проверить его на соответствие схеме XSD без дополнительных манипуляций. Однако для решения прикладных задач интеграции описанные выше методы являются полностью рабочими и надежными.

← На главную