Как передать секцию CDATA через фабрику XDTO в 1С?

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

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

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

Выясним причину проблемы при работе с XDTO

Рассмотрим, почему обычное присвоение строки с блоком CDATA свойству объекта XDTO не дает нужного результата. В стандарте XML Schema (XSD) не существует отдельного типа данных для CDATA — с точки зрения схемы это обычная строка. Когда мы присваиваем свойству объекта XDTO строковое значение, содержащее <![CDATA[...]]>, механизм сериализации XDTO выполняет автоэкранирование служебных символов XML. В результате символы < и > превращаются в &lt; и &gt;, а внешняя система получает экранированный текст вместо блока CDATA.

Если же попытаться передать такую строку без правильной обработки структуры, платформа 1С на этапе валидации или отправки может выдать ошибку с указанием на то, что вместо символа ! ожидает разделитель <.

Способ 1. Использование последовательности XDTO и свойства __content

Если схема XSD допускает смешанное содержимое (mixed content) у элемента, для манипуляции с открытым текстом или специальными фрагментами в объектах XDTO используется механизм последовательностей и служебное свойство __content.

Проанализируем пример работы с последовательностью объекта XDTO:


// Получаем объект последовательности из объекта XDTO
Последовательность = ОбъектXDTO.Последовательность();

// Добавляем текст в специальное свойство __content
Последовательность.Добавить(ОбъектXDTO.Свойства().Получить("__content"), ТекстXML);

Использование свойства __content и вызова Последовательность() позволяет управлять записью неэкранированного текста на уровне объекта XDTO, если это поддерживается моделью типа.

Способ 2. Формирование XML с помощью объекта ЗаписьXML

Если встроенная сериализация WSПрокси заменяет спецсимволы на сущности XML, самым надежным способом является явная сборка XML-документа с помощью объекта ЗаписьXML.

У объекта ЗаписьXML есть специализированный метод ЗаписатьСекциюCDATA(), который формирует корректный блок без экранирования входящих в него тегов. Рассмотрим пример создания такого документа:


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

Запись.ЗаписатьОбъявлениеXML();
Запись.ЗаписатьНачалоЭлемента("SEATS");

// Формируем текст для вставки в CDATA
ТекстData = "<SEAT><GOODS_TYPE_ID>2</GOODS_TYPE_ID></SEAT>";

// Записываем секцию CDATA
Запись.ЗаписатьСекциюCDATA(ТекстData);

Запись.ЗаписатьКонецЭлемента(); // SEATS

РезультатXML = Запись.Закрыть();

Также при наличии готовой строки, содержащей готовый сформированный блок, можно применить метод ЗаписатьБезОбработки(), который выгружает переданный фрагмент в XML-поток без любых синтаксических изменений.

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

Если обработка структуры выполняется в памяти в виде дерева узлов, можно использовать объект ДокументDOM и его метод СоздатьСекциюCDATA().

Разберем по шагам создание CDATA-узла:


ДокументDOM = Новый ДокументDOM;
КорневойУзел = ДокументDOM.СоздатьЭлемент("SEATS");
ДокументDOM.ВставитьПеред(КорневойУзел, Неопределено);

// Создаем секцию CDATA
УзелCDATA = ДокументDOM.СоздатьСекциюCDATA(ТекстЗапроса);
КорневойУзел.СвязатьУзел(УзелCDATA);

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

ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(ДокументDOM, Запись);

Результат = Запись.Закрыть();

Способ 4. Низкоуровневая отправка SOAP-запроса через HTTPСоединение

В случаях, когда сторонний веб-сервис строго требует наличие секции CDATA внутри SOAP-конверта, а высокоуровневый `WSПрокси` заменяет спецсимволы сущностями, необходимо перейти на прямую отправку SOAP-запроса через HTTP.

Рассмотрим алгоритм реализации:

  1. Формируем полный текст SOAP-конверта (Envelope, Body) вручную с помощью ЗаписьXML (применяя ЗаписатьСекциюCDATA()) или через текстовый шаблон.
  2. Создаем объект HTTPСоединение и подготавливаем HTTPЗапрос.
  3. Задаем необходимые заголовки запроса: Content-Type (например, text/xml; charset=utf-8) и заголовок SOAPAction.
  4. Отправляем HTTP-запрос методом POST и обрабатываем полученный ответ сервера.

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

← На главную