Как распарсить XML, закодированный в base64Binary, в 1С без использования временных файлов

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

При интеграции 1С с внешними веб-сервисами через HTTP-запросы часто возникает ситуация, когда в теле ответа приходит не чистый текст или JSON, а структура XML, где полезные данные упакованы в тег с типом base64Binary. На первый взгляд это кажется избыточным, но таков стандарт многих SOAP и REST-сервисов. В этой статье мы разберем, как элегантно извлечь эти данные, декодировать их и превратить в полноценный объект XML, не нагружая дисковую подсистему созданием временных файлов.

Анализ проблемы: что скрывается за base64Binary

Рассмотрим ситуацию, когда после выполнения HTTPЗапрос мы получаем ответ, тело которого выглядит примерно так:


<base64Binary xmlns="http://tempuri.org/">PD94bWwgdmVyc2lvbj0iMS4wIj8+DQo8cmVzcG9uc2U+...</base64Binary>

Проблема заключается в том, что внутри XML-тега находится строка, закодированная по алгоритму Base64. Сама по себе эта строка — это «слепок» другого файла (в нашем случае — вложенного XML). Чтобы добраться до данных, нам нужно пройти три этапа:

  1. Извлечь текстовое содержимое тега base64Binary.
  2. Преобразовать эту строку в ДвоичныеДанные.
  3. Декодировать двоичные данные в понятный 1С текст или сразу в объект ЧтениеXML.

Этап 1: Извлечение Base64-строки из HTTP-ответа

Первым делом нам нужно получить саму зашифрованную строку. Если мы используем метод Ответ.ПолучитьТелоКакСтроку(), мы получим весь XML-контейнер. Чтобы достать только «начинку», проанализируем наиболее эффективные способы. Можно использовать строковые функции СтрНайти и Сред, но это ненадежно, если структура XML изменится. Правильнее использовать объект ЧтениеXML.

Рассмотрим пример кода для быстрого извлечения значения:


Чтение = Новый ЧтениеXML;
Чтение.УстановитьСтроку(ОтветHTTP.ПолучитьТелоКакСтроку());

Base64Строка = "";
Пока Чтение.Прочитать() Цикл
    Если Чтение.ТипУзла = ТипУзлаXML.НачалоЭлемента И Чтение.Имя = "base64Binary" Тогда
        Base64Строка = Чтение.ПрочитатьСодержимоеКакСтроку();
        Прервать;
    КонецЕсли;
КонецЦикла;

Использование метода ПрочитатьСодержимоеКакСтроку() позволяет нам сразу получить очищенные данные, находящиеся внутри тегов, игнорируя служебные символы XML.

Этап 2: Преобразование строки в ДвоичныеДанные

Теперь, когда у нас есть «сырая» Base64-строка, воспользуемся встроенной функцией платформы Base64Значение(). Проанализируем, что она делает: она переводит текстовое представление байтов обратно в объект типа ДвоичныеДанные.

ДвоичныеДанныеДекодированные = Base64Значение(Base64Строка);

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

Этап 3: Получение XML в памяти (современный подход)

В старых версиях платформы 1С действительно было сложно обойтись без временного файла. Однако, начиная с версии 8.3.10, у нас есть мощный инструмент — метод ПолучитьСтрокуИзДвоичныхДанных(). Разберем, как его применить.

Выясним причину, почему важно указывать кодировку. XML внутри Base64 чаще всего закодирован в UTF-8. Если не указать это явно, система может использовать кодировку по умолчанию, что приведет к ошибке при попытке чтения XML-структуры.


// Преобразуем двоичные данные в обычную строку XML
СтрокаXML = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанныеДекодированные, КодировкаТекста.UTF8);

// Теперь загружаем эту строку в парсер
ЧтениеРезультата = Новый ЧтениеXML;
ЧтениеРезультата.УстановитьСтроку(СтрокаXML);

Пока ЧтениеРезультата.Прочитать() Цикл
    // Здесь выполняем обход узлов полученного внутреннего XML
    // Например: Если ЧтениеРезультата.Имя = "id" Тогда ...
КонецЦикла;

Этап 4: Использование потоков для больших данных (v8.3.15+)

Если объем данных в base64Binary велик (например, выгрузка на несколько десятков мегабайт), преобразование в «тяжелую» строку может существенно замедлить работу и вызвать нехватку оперативной памяти. В современных версиях платформы (8.3.15 и выше) мы можем использовать потоки. Посмотрим на этот профессиональный метод:


// Создаем поток в памяти из полученных двоичных данных
Поток = Новый ПотокВПамяти(ДвоичныеДанныеДекодированные);

// Инициализируем чтение XML напрямую из потока
ЧтениеXMLПоток = Новый ЧтениеXML;
ЧтениеXMLПоток.ОткрытьПоток(Поток);

// Читаем данные привычным способом
Пока ЧтениеXMLПоток.Прочитать() Цикл
    // Логика обработки данных
КонецЦикла;

ЧтениеXMLПоток.Закрыть();
Поток.Закрыть();

Этот способ является максимально производительным, так как данные передаются практически «напрямую» из бинарного вида в парсер, минуя стадию создания огромных текстовых строк в памяти.

Альтернатива: Десериализация через XDTO

Если у вас есть XSD-схема или вы работаете с типизированными данными, процесс можно еще больше автоматизировать. Тип xs:base64Binary — стандартный для XDTO. Разберем, как 1С работает с ним автоматически.

Если вы используете ФабрикаXDTO для чтения всего HTTP-ответа, то при наличии описания типа, платформа самостоятельно преобразует содержимое тега base64Binary в объект ДвоичныеДанные. Вам останется только выполнить декодирование строки из этих данных, как было показано выше.

Важные нюансы и обработка ошибок

При работе с Base64 и XML следует учитывать несколько критически важных моментов:

  1. Наличие BOM (Byte Order Mark): Иногда в начале декодированной строки могут присутствовать невидимые символы (маркеры последовательности байтов). Если ЧтениеXML.УстановитьСтроку() выдает ошибку в первой позиции, попробуйте предварительно очистить строку или использовать метод с потоками, который лучше справляется с определением кодировки.
  2. Пробелы и переносы: В некоторых реализациях Base64-строка может содержать переносы строк для читаемости. Метод Base64Значение() в 1С обычно игнорирует такие символы, но если вы получаете ошибку «Недопустимый символ», стоит проверить строку на наличие лишних пробелов с помощью СтрЗаменить(Стр, Символы.ПС, "").
  3. Тип содержимого: Убедитесь, что внутри Base64 действительно XML. Иногда там может оказаться PDF-документ или изображение. Проверить это можно, взглянув на первые символы декодированной строки — для XML это обычно <?xml.

Подведем итог: использование временных файлов для обработки Base64 — это пережиток прошлого. Используя ПолучитьСтрокуИзДвоичныхДанных или ПотокВПамяти, мы делаем наш код чище, быстрее и современнее. Проанализировав эти методы, вы сможете выбрать наиболее подходящий под ваши задачи и версию платформы.

← На главную