Как устранить появление лишних отступов и пробелов при записи ХранилищаЗначения в XML в 1С?

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

При выгрузке и обмене данными разработчики нередко сталкиваются с ситуацией, когда данные объекта ХранилищеЗначения после выгрузки в XML-документ не удается прочитать на стороне приемника. Проанализируем типичный сценарий: отправитель сериализует хранилище с помощью конструкции ЗаписьXML.ЗаписатьТекст(XMLСтрока(ХранилищеЗначения)), а на стороне приемника в текстовом представлении данных появляются лишние пробелы или табуляции в начале каждой строки. В результате процедура десериализации выдает ошибку, так как строка Base64 оказывается поврежденной.

Выясним причину такого поведения платформы 1С и разберем по шагам надежные способы решения проблемы как на стороне источника, так и на стороне приемника.

Почему возникают искажения в строке данных?

Рассмотрим механизм формирования строки. Функция XMLСтрока() для объекта ХранилищеЗначения генерирует строку в формате Base64. По стандарту длинные Base64-последовательности автоматически разбиваются на строки фиксированной длины с помощью символов перевода строки.

Если для объекта ЗаписьXML включено форматирование (установлен отступ в объекте ПараметрыЗаписиXML для формирования «красивого» XML с отступами узлов), платформа начинает форматировать каждую новую строку внутри текстового содержимого тега, добавляя туда пробелы или символы табуляции. При последующем чтении эти служебные отступы считываются парсером как полезная нагрузка, нарушая целостность Base64-кода.

Способ 1. Использование штатной сериализации платформы 1С

Наиболее корректным подходом является отказ от ручного преобразования через XMLСтрока() и метод ЗаписатьТекст(). Платформа 1С:Предприятие умеет самостоятельно сериализовать и десериализовать объекты типа ХранилищеЗначения.

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


// Создаем или получаем ХранилищеЗначения
Хранилище = Новый ХранилищеЗначения(ИсходныеДанные);

// Выполняем запись напрямую через платформенный метод
ЗаписатьXML(ЗаписьXML, Хранилище);

На стороне приемника чтение выполняется симметрично с помощью функции ПрочитатьXML():


// Чтение объекта из текущего положения парсера XML
ВосстановленноеХранилище = ПрочитатьXML(ЧтениеXML);
Данные = ВосстановленноеХранилище.Получить();

При таком способе платформа самостоятельно управляет типами данных и кодированием, исключая искажение информации сторонними отступами.

Способ 2. Запись содержимого в секцию CDATA

Если структура формируемого XML-файла требует вставки именно текстового узла или сторонний сервис ожидает данные внутри определенного тега, экранируем текст с помощью секции CDATA. Данные внутри секции CDATA не подвергаются форматированию парсером.

Разберем пример записи:


ЗаписьXML.ЗаписатьНачалоЭлемента("ДанныеХранилища");
ЗаписьXML.ЗаписатьСекциюCDATA(XMLСтрока(Хранилище));
ЗаписьXML.ЗаписатьКонецЭлемента();

Способ 3. Отключение автоматических отступов в параметрах записи XML

Если требуется выгрузить «чистый» XML без лишних пробельных символов, отключим форматирование при инициализации объекта ЗаписьXML.

Посмотрим, как настроить параметры:


Параметры = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Ложь);
ЗаписьXML.ОткрытьФайл(ПутьКФайлу, Параметры);

Третий параметр Ложь отключает автоматическую расстановку отступов в строках, благодаря чему текстовые блоки Base64 сохраняются в исходном виде.

Способ 4. Явное кодирование в Base64 через ДвоичныеДанные

Еще один надежный вариант передачи данных — предварительное приведение объекта к двоичным данным и получение Base64-строки без форматирования:


// Преобразуем данные в двоичный формат и кодируем в Base64
Двоичные = Новый ДвоичныеДанные(ИмяФайлаИсточника);
СтрокаBase64 = Base64Строка(Двоичные);

ЗаписьXML.ЗаписатьНачалоЭлемента("Данные");
ЗаписьXML.ЗаписатьТекст(СтрокаBase64);
ЗаписьXML.ЗаписатьКонецЭлемента();

Способ 5. Очистка строки от лишних пробелов на стороне приемника

Бывают ситуации, когда изменить логику формирования XML на стороне источника невозможно. В таком случае устраним проблему на этапе чтения, удалив из считанной строки все паразитные символы до передачи в XMLЗначение() или Base64Значение().

Разберем по шагам процедуру нормализации строки:


// Считываем «грязную» строку из узла XML
СчитаннаяСтрока = ЧтениеXML.Значение;

// Удаляем пробелы, табуляции и переводы строк
ОчищеннаяСтрока = СтрЗаменить(СчитаннаяСтрока, " ", "");
ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, Символы.Таб, "");
ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, Символы.ПС, "");
ОчищеннаяСтрока = СтрЗаменить(ОчищеннаяСтрока, Символы.ВК, "");

// Восстанавливаем объект ХранилищеЗначения
Хранилище = XMLЗначение(Тип("ХранилищеЗначения"), ОчищеннаяСтрока);
Результат = Хранилище.Получить();

Рекомендация: Для типовых обменов между конфигурациями 1С всегда отдавайте предпочтение функциям ЗаписатьXML() и ПрочитатьXML(). Если обмен происходит со сторонними системами, используйте секцию CDATA либо явную очистку пробельных символов перед декодированием Base64.

← На главную