При работе с интеграциями программисты 1С часто сталкиваются с жестким требованием принимающей стороны: XML-файл не должен содержать объявлений пространств имен (атрибуты xmlns) в корневом теге или вложенных элементах. Однако ФабрикаXDTO, работающая по стандартам XML Schema, по умолчанию всегда добавляет эти данные, так как они являются фундаментом типизации XDTO. В этой статье мы разберем несколько способов, как обойти это ограничение и получить "чистый" XML, сохранив при этом удобство работы с объектами XDTO.
Проанализируем ситуацию: когда мы вызываем метод ФабрикаXDTO.ЗаписатьXML(), система обращается к метаданным пакета XDTO. Если у пакета заполнен атрибут targetNamespace (целевое пространство имен), платформа обязана указать его в результирующем файле, чтобы документ соответствовал схеме. Даже если мы программно создаем объект, он остается привязанным к своему типу внутри пространства имен. Рассмотрим, какие существуют обходные пути, чтобы исключить эти атрибуты из финального текста.
Это наиболее элегантный программный метод. Суть его заключается в том, что мы не отдаем весь объект целиком на откуп фабрике, а берем на себя формирование корневого узла. Выясним, как это реализовать на практике. Мы создаем объект ЗаписьXML, вручную записываем начало элемента без указания URI, а затем используем фабрику только для сериализации вложенного содержимого.
Рассмотрим пример кода:
// Создаем объект записи и параметры
Запись = Новый ЗаписьXML;
ПараметрыЗаписи = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Истина);
Запись.ОткрытьФайл(ПутьКФайлу, ПараметрыЗаписи);
Запись.ЗаписатьОбъявлениеXML();
// Записываем корневой тег вручную БЕЗ пространства имен
Запись.ЗаписатьНачалоЭлемента("RootElementName");
// Допустим, ОбъектXDTO — это наш подготовленный объект
// Перебираем все свойства объекта и записываем их через фабрику
Для каждого Свойство Из ОбъектXDTO.Тип().Свойства Цикл
ЗначениеСвойства = ОбъектXDTO.Получить(Свойство.Имя);
Если ЗначениеСвойства <> Неопределено Тогда
// Записываем вложенные элементы, подавляя определение типов
ФабрикаXDTO.ЗаписатьXML(Запись, ЗначениеСвойства, Свойство.Имя, , , ВариантУзлаXML.Никто);
КонецЕсли;
КонецЦикла;
// Закрываем корень вручную
Запись.ЗаписатьКонецЭлемента();
Запись.Закрыть();
Этот метод позволяет полностью избежать появления xmlns в самом верхнем теге, сохраняя автоматизацию для всех вложенных структур.
Если структура XML сложная и гибридный метод реализовать затруднительно, мы можем воспользоваться встроенными механизмами DOM (Document Object Model). Проанализируем этот подход: сначала мы генерируем "грязный" XML в память, затем загружаем его в дерево DOM, программно удаляем ненужные атрибуты и сохраняем результат. Это гораздо надежнее, чем простая замена строк в текстовом редакторе.
Посмотрим на последовательность действий:
ЗаписьXML, который пишет в память (строку).ПостроительDOM и читаем полученную строку.Документ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, ЗаписьИтог);
ЗаписьИтог.Закрыть();
Если вам мешают префиксы (например, d4p1:Name) внутри самого тела XML, можно изменить настройки самого XDTO-пакета. Разберем, как это влияет на визуальное представление данных. В редакторе пакета у каждого элемента (или у самого пакета для всех вложенных свойств) есть свойство Форма (Form).
Если установить значение Unqualified, платформа перестанет добавлять префиксы пространств имен к дочерним элементам. Это сделает структуру более читаемой. Однако стоит помнить, что это не уберет главное объявление xmlns в корне. Поэтому данный метод обычно используется как вспомогательный вместе с первым или вторым способом.
Существует продвинутый способ: создание типов "на лету" без привязки к конкретному пространству имен. Если использовать объект МодельXDTO и программно описывать типы, не назначая им targetNamespace, то при выгрузке фабрика может не найти URI для сопоставления и выдаст чистые теги. Но этот путь трудозатратен, так как требует ручного описания всей структуры данных в коде вместо использования визуального конструктора.
Подведем итог нашему анализу. Выбор метода зависит от ваших ограничений:
Важно помнить, что удаление пространств имен делает XML технически "анонимным", и стандартные валидаторы не смогут проверить его на соответствие схеме XSD без дополнительных манипуляций. Однако для решения прикладных задач интеграции описанные выше методы являются полностью рабочими и надежными.