Как правильно передать HTML-текст с сервера на клиент в 1С и избежать ошибки разбора XML?

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

При разработке функционала для работы с электронной почтой или при отображении сложных веб-страниц внутри 1С программисты часто сталкиваются с ситуацией, когда необходимо передать полученный на сервере HTML-текст на сторону клиента для его отображения в ПолеHTMLДокумента. Казалось бы, задача тривиальная — передать строку через структуру или параметр функции. Однако на практике система нередко выдает загадочную ошибку: «Ошибка разбора XML: -[1,1]».

В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем механизмы сериализации данных в 1С и рассмотрим несколько надежных способов передачи «проблемных» строк, которые гарантированно избавят вас от ошибок разбора.

Выясним причину возникновения ошибки разбора XML

Прежде чем переходить к коду, давайте поймем физику процесса. В платформе 1С:Предприятие 8 передача данных между сервером и тонким (или веб-) клиентом происходит не напрямую. Все данные, которые мы возвращаем из серверной функции, упаковываются во внутренний формат обмена, основанный на XML.

Проблема заключается в том, что стандарт XML 1.0 накладывает жесткие ограничения на используемые символы. В частности, запрещены так называемые «непечатные» управляющие символы ASCII в диапазоне 0x00–0x1F (за исключением символов табуляции, перевода строки и возврата каретки). Поскольку HTML-текст писем часто формируется сторонними почтовыми клиентами или парсерами, в нем могут содержаться невидимые спецсимволы, например, нулевой байт \0. Как только такой символ попадает в поток сериализации, XML-парсер 1С на приемной стороне (на клиенте) «спотыкается», выдавая ошибку в первой позиции первой строки — -[1,1].

Способ 1: Использование двоичных данных (Рекомендация из типовых решений)

Рассмотрим наиболее простой и эффективный метод, который часто применяется в типовых конфигурациях от фирмы 1С. Суть метода заключается в том, что мы превращаем строку в ДвоичныеДанные. Двоичные данные сериализуются платформой без попыток анализа их содержимого, что позволяет безопасно «протащить» любые запрещенные символы.

Разберем по шагам реализацию этого метода. На стороне сервера мы преобразуем полученный HTML-текст в поток байтов:


&НаСервере
Функция ПолучитьТелоПисьмаНаСервере()
    
    // Предположим, мы получили HTML-текст из почтового сообщения
    ТекстHTML = "Пример текста с возможной 'запрещенкой'...";
    
    // Преобразуем строку в двоичные данные, используя кодировку UTF-8
    ДанныеДляПередачи = ПолучитьДвоичныеДанныеИзСтроки(ТекстHTML, КодировкаТекста.UTF8, Ложь);
    
    Возврат ДанныеДляПередачи;
КонецФункции

Теперь на клиенте нам нужно выполнить обратную операцию, чтобы передать текст в реквизит, связанный с полем HTML-документа:


&НаКлиенте
Процедура ПоказатьПисьмо()
    
    ДвоичныеДанные = ПолучитьТелоПисьмаНаСервере();
    
    // Восстанавливаем строку из двоичных данных
    Объект.ТекстHTMLПоле = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанные, КодировкаТекста.UTF8);
    
КонецПроцедуры

Важный нюанс: Обратите внимание на использование третьего параметра в функции ПолучитьДвоичныеДанныеИзСтроки — это флаг добавления BOM (Byte Order Mark). Мы установили его в Ложь, чтобы избежать появления лишних артефактов в начале HTML-кода, которые могут некорректно интерпретироваться движком отображения (особенно в Internet Explorer).

Способ 2: Передача через Временное хранилище

Если объем передаваемого HTML-текста велик (например, длинная переписка с внедренными картинками в формате Base64), передача через параметры функции может негативно сказаться на производительности. В этом случае проанализируем возможность использования Временного хранилища.

Этот механизм работает в обход стандартной XML-сериализации параметров вызова процедуры, что делает его не только безопасным с точки зрения символов, но и более быстрым. Рассмотрим алгоритм:

  1. На сервере помещаем данные в хранилище и получаем уникальный адрес.
  2. Передаем только адрес (короткую строку) на клиент.
  3. На клиенте извлекаем данные по адресу.

Посмотрим на пример кода:


&НаСервере
Функция ПоместитьHTMLВоХранилище()
    
    ТекстHTML = "Большой объем данных...";
    
    // Помещаем во временное хранилище, привязывая к уникальному идентификатору формы
    АдресХранилища = ПоместитьВоВременноеХранилище(ТекстHTML, ЭтаФорма.УникальныйИдентификатор);
    
    Возврат АдресХранилища;
КонецФункции

&НаКлиенте
Процедура ЗагрузитьHTML()
    
    Адрес = ПоместитьHTMLВоХранилище();
    
    // Извлекаем данные на клиенте
    ТекстДляПоля = ПолучитьИзВременногоХранилища(Адрес);
    Объект.ТекстHTMLПоле = ТекстДляПоля;
    
КонецПроцедуры

Способ 3: Очистка строки от запрещенных символов

Иногда нам принципиально важно передать именно тип Строка (например, если это требуется интерфейсом взаимодействия внешних систем). В такой ситуации мы можем применить фильтрацию. Разберем ситуацию: нам нужно удалить все символы с кодами меньше 32, которые не являются стандартными переносами строк.

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


&НаСервере
Функция ОчиститьСтрокуДляXML(Знач ИсходнаяСтрока)
    
    // Оставляем только допустимые символы: Tab (9), LF (10), CR (13) и все от Space (32)
    Результат = "";
    Для Позиция = 1 По СтрДлина(ИсходнаяСтрока) Цикл
        КодСимвола = КодСимвола(ИсходнаяСтрока, Позиция);
        Если КодСимвола >= 32 Или КодСимвола = 9 Или КодСимвола = 10 Или КодСимвола = 13 Тогда
            Результат = Результат + Сред(ИсходнаяСтрока, Позиция, 1);
        КонецЕсли;
    КонецЦикла;
    
    Возврат Результат;
КонецФункции

Совет: Если строка очень длинная, перебор символов в цикле 1С может работать медленно. В таких случаях эффективнее использовать регулярные выражения через COM-объект VBScript.RegExp, если сервер работает под управлением ОС Windows.

Особенности отображения и оптимизация трафика

При работе с ПолемHTMLДокумента важно учитывать еще несколько моментов, которые помогут сделать работу приложения более стабильной:

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

← На главную