При формировании XML-документов с помощью механизма XDTO разработчики часто сталкиваются с неожиданным поведением платформы: при сериализации объекта через метод ФабрикаXDTO.ЗаписатьXML() дочерние узлы получают пустой атрибут пространства имен xmlns="". В результате формируется XML следующего вида:
<Объект xmlns="МоеПространство">
<МоеСвойство xmlns="">Значение свойства</МоеСвойство>
</Объект>
В этой статье мы подробно разберем, почему платформа 1С добавляет такой атрибут, как устроены стандарты XML Schema и какими способами можно сформировать корректную итоговую структуру XML без нежелательных пустых пространств имен.
Проанализируем ситуацию на уровне спецификации W3C XML Schema. В схемах XSD по умолчанию действует правило elementFormDefault="unqualified". В платформе 1С:Предприятие этому правилу соответствует свойство XDTO-пакета Квалифицированная форма элементов, установленное в значение Ложь.
Разберем подробнее, что означает неквалифицированная форма (unqualified):
Объект.no namespace).Когда платформа 1С сериализует корневой элемент с указанием пространства имен по умолчанию (xmlns="МоеПространство"), по законам синтаксиса XML все дочерние узлы автоматически наследуют это пространство. Чтобы строго следовать описанию схемы XSD и оставить вложенный элемент в пустом пространстве имен, сериализатор 1С вынужден явно аннулировать унаследованное пространство, добавляя атрибут xmlns="". Таким образом, платформа действует строго по стандарту.
Если XDTO-пакет разрабатывается внутри вашей конфигурации и структура XML-документа полностью контролируется вами, самое быстрое и правильное решение — включить квалификацию для всех элементов пакета.
Разберем по шагам, как это сделать в конфигураторе:
elementFormDefault="qualified" в XSD).После включения этого свойства все вложенные элементы официально признаются принадлежащими пространству имен МоеПространство. Платформе больше не потребуется сбрасывать пространство имен, и XML примет аккуратный вид:
<Объект xmlns="МоеПространство">
<МоеСвойство>Значение свойства</МоеСвойство>
</Объект>
Важное ограничение: если схема предоставлена сторонней системой (например, государственным сервисом или банком) и у контрагента жестко задан параметр elementFormDefault="unqualified", изменение этого свойства на Истина изменит контракт данных. В таком случае принимающая сторона выдаст ошибку валидации схемы XSD, так как элементы из пространства МоеПространство для нее будут невалидными.
Выясним причину, почему возникает сброс: он происходит только тогда, когда пространство имен объявляется как пространство по умолчанию через xmlns="...". Если корневой тег выводится с префиксом, пространство имен по умолчанию не переопределяется.
В этом случае вложенный неквалифицированный элемент выводится без префикса, остается в пустом пространстве имен по правилам схемы и не требует сброса через xmlns="":
<ns:Объект xmlns:ns="МоеПространство">
<МоеСвойство>Значение свойства</МоеСвойство>
</ns:Объект>
Чтобы заставить платформу использовать конкретный префикс при записи, настроим объект ЗаписьXML перед вызовом сериализации XDTO. Посмотрим на пример кода:
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
// Явно связываем префикс с пространством имен
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен("ns", "МоеПространство");
// Выполняем запись объекта XDTO
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектXDTO);
ИтоговыйXML = ЗаписьXML.Закрыть();
При таком подходе мы сохраняем строгое соответствие схеме с elementFormDefault="unqualified", но избавляемся от лишних атрибутов сброса пространства в теле документа.
Если мы работаем со схемой напрямую через файл XSD или динамически создаем модель фабрики XDTO, нет необходимости включать квалификацию для всего пакета целиком. Можно управлять квалификацией на уровне конкретного свойства.
Для отдельного элемента в описании XSD достаточно указать атрибут form="qualified". В этом случае только этот конкретный элемент будет квалифицирован целевым пространством имен, а остальные свойства останутся неквалифицированными согласно общим настройкам пакета.
Иногда возникают ситуации, когда внешняя система использует примитивный парсер, не умеющий корректно считывать теги с xmlns="", но при этом пакет изменять нельзя. В таких случаях можно применить постобработку выгруженного XML с помощью объекта платформы ПреобразованиеXSL.
С помощью простого шаблона преобразования XSLT можно на лету удалить пустые объявления пространств имен перед отправкой строки в целевой сервис.
Появление тегов вида <МоеСвойство xmlns=""> — это штатное поведение платформы 1С, продиктованное стандартом W3C XML Schema при неквалифицированной форме элементов пакета. Для устранения этого атрибута используйте установку свойства Квалифицированная форма элементов = Истина (если схема контролируется вами) либо привязку пространства имен к префиксу через ЗаписьСоответствиеПространстваИмен() (если схема зафиксирована сторонней системой).