Почему дочерние свойства объекта XDTO отвязываются от пространства имен в 1С?

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

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


<Объект xmlns="МоеПространство">
    <МоеСвойство xmlns="">Значение свойства</МоеСвойство>
</Объект>

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

Причина поведения: стандарты XML Schema и логика платформы

Проанализируем ситуацию на уровне спецификации W3C XML Schema. В схемах XSD по умолчанию действует правило elementFormDefault="unqualified". В платформе 1С:Предприятие этому правилу соответствует свойство XDTO-пакета Квалифицированная форма элементов, установленное в значение Ложь.

Разберем подробнее, что означает неквалифицированная форма (unqualified):

  1. Глобальные элементы схемы всегда принадлежат целевому пространству имен (target namespace). В нашем примере это корневой узел Объект.
  2. Локальные (вложенные) элементы по умолчанию не принадлежат целевому пространству имен пакета — формально они находятся в пустом пространстве имен (no namespace).

Когда платформа 1С сериализует корневой элемент с указанием пространства имен по умолчанию (xmlns="МоеПространство"), по законам синтаксиса XML все дочерние узлы автоматически наследуют это пространство. Чтобы строго следовать описанию схемы XSD и оставить вложенный элемент в пустом пространстве имен, сериализатор 1С вынужден явно аннулировать унаследованное пространство, добавляя атрибут xmlns="". Таким образом, платформа действует строго по стандарту.

Решение 1. Включение квалифицированной формы элементов в XDTO-пакете

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

Разберем по шагам, как это сделать в конфигураторе:

  1. Откроем дерево метаданных и найдем нужный Пакет XDTO в ветке Общие > XDTO-пакеты.
  2. Перейдем в окно свойств пакета XDTO.
  3. Найдем свойство Квалифицированная форма элементов и установим его в значение Истина (что соответствует elementFormDefault="qualified" в XSD).

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


<Объект xmlns="МоеПространство">
    <МоеСвойство>Значение свойства</МоеСвойство>
</Объект>

Важное ограничение: если схема предоставлена сторонней системой (например, государственным сервисом или банком) и у контрагента жестко задан параметр elementFormDefault="unqualified", изменение этого свойства на Истина изменит контракт данных. В таком случае принимающая сторона выдаст ошибку валидации схемы XSD, так как элементы из пространства МоеПространство для нее будут невалидными.

Решение 2. Использование явных префиксов пространств имен

Выясним причину, почему возникает сброс: он происходит только тогда, когда пространство имен объявляется как пространство по умолчанию через xmlns="...". Если корневой тег выводится с префиксом, пространство имен по умолчанию не переопределяется.

В этом случае вложенный неквалифицированный элемент выводится без префикса, остается в пустом пространстве имен по правилам схемы и не требует сброса через xmlns="":


<ns:Объект xmlns:ns="МоеПространство">
    <МоеСвойство>Значение свойства</МоеСвойство>
</ns:Объект>

Чтобы заставить платформу использовать конкретный префикс при записи, настроим объект ЗаписьXML перед вызовом сериализации XDTO. Посмотрим на пример кода:


ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();

// Явно связываем префикс с пространством имен
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("ns", "МоеПространство");

// Выполняем запись объекта XDTO
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектXDTO);

ИтоговыйXML = ЗаписьXML.Закрыть();

При таком подходе мы сохраняем строгое соответствие схеме с elementFormDefault="unqualified", но избавляемся от лишних атрибутов сброса пространства в теле документа.

Решение 3. Точечная квалификация отдельных свойств

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

Для отдельного элемента в описании XSD достаточно указать атрибут form="qualified". В этом случае только этот конкретный элемент будет квалифицирован целевым пространством имен, а остальные свойства останутся неквалифицированными согласно общим настройкам пакета.

Решение 4. Нормализация через XSLT-преобразование

Иногда возникают ситуации, когда внешняя система использует примитивный парсер, не умеющий корректно считывать теги с xmlns="", но при этом пакет изменять нельзя. В таких случаях можно применить постобработку выгруженного XML с помощью объекта платформы ПреобразованиеXSL.

С помощью простого шаблона преобразования XSLT можно на лету удалить пустые объявления пространств имен перед отправкой строки в целевой сервис.

Итоги

Появление тегов вида <МоеСвойство xmlns=""> — это штатное поведение платформы 1С, продиктованное стандартом W3C XML Schema при неквалифицированной форме элементов пакета. Для устранения этого атрибута используйте установку свойства Квалифицированная форма элементов = Истина (если схема контролируется вами) либо привязку пространства имен к префиксу через ЗаписьСоответствиеПространстваИмен() (если схема зафиксирована сторонней системой).

← На главную