При работе с объектной моделью документа (DOM) в 1С программисты часто сталкиваются с тем, что при попытке вставить тег br или любую другую HTML-разметку внутрь элемента, система автоматически преобразует символы < и > в безопасные сущности < и >. В итоге вместо ожидаемого переноса строки пользователь видит на странице сырой текст тега. Рассмотрим подробнее, почему это происходит и какими способами можно добиться корректного отображения переноса строки.
Разберем ситуацию на примере стандартного кода. Когда мы используем метод СоздатьЭлемент и устанавливаем значение через свойство ТекстовоеСодержимое (аналог textContent в JS), платформа 1С строго следует стандартам XML/HTML. Это свойство предназначено исключительно для текста. Любые управляющие символы разметки внутри него рассматриваются как часть текстовой информации, которую нужно вывести "как есть", поэтому они экранируются для защиты от некорректной интерпретации браузером.
Посмотрим на типичный ошибочный код:
парДок = док.СоздатьЭлемент("h1");
// Попытка вставить тег напрямую в текст приведет к экранированию
парДок.ТекстовоеСодержимое = "Номер: " + Объект.Номер + " <br> Дата: " + Объект.Дата;
телДок.ДобавитьДочерний(парДок);
В результате работы этого кода в итоговом HTML-файле мы получим строку: <h1>Номер: 123 <br> Дата: 01.01.2024</h1>. Браузер отобразит тег текстом, а не выполнит перенос.
Проанализируем самый быстрый и эффективный способ решения задачи. Если нам необходимо передать строку, содержащую готовую HTML-разметку (например, текст с тегами br, b, i), следует использовать свойство ВнутреннийHTML (или InnerHTML в зависимости от используемой версии платформы и объектов).
Это свойство указывает парсеру, что содержимое не является простым текстом и его нужно обработать как часть структуры документа. В этом случае теги не будут экранированы.
парДок = док.СоздатьЭлемент("h1");
// Используем ВнутреннийHTML вместо ТекстовоеСодержимое
парДок.ВнутреннийHTML = "" + Объект.Номер + " <br> " + Формат(Объект.Дата, "ДФ=dd.MM.yyyy");
телДок.ДобавитьДочерний(парДок);
Выясним, как решить задачу максимально "чисто" с точки зрения архитектуры DOM, не прибегая к записи сырых строк. Правильный путь — это создание отдельных узлов для текста и отдельного узла-элемента для переноса строки.
Разберем этот процесс по шагам:
br.h1.Пример программной реализации:
парДок = док.СоздатьЭлемент("h1");
// 1. Создаем первый текстовый блок
ТекстНомер = док.СоздатьТекстовыйУзел("" + Объект.Номер);
парДок.ДобавитьДочерний(ТекстНомер);
// 2. Создаем элемент переноса строки
Разделитель = док.СоздатьЭлемент("br");
парДок.ДобавитьДочерний(Разделитель);
// 3. Создаем второй текстовый блок
ТекстДата = док.СоздатьТекстовыйУзел(Формат(Объект.Дата, "ДФ=dd.MM.yyyy"));
парДок.ДобавитьДочерний(ТекстДата);
телДок.ДобавитьДочерний(парДок);
Преимущество этого метода: Полная безопасность данных. Вам не нужно беспокоиться о том, что в номере объекта могут встретиться спецсимволы, которые сломают верстку — платформа сама позаботится о корректности каждого узла.
Иногда использование тега br не является обязательным, если ваша цель — просто визуально разделить строки. Мы можем воспользоваться стандартными символами переноса строки 1С (Символы.ПС), если настроим соответствующее отображение в стилях HTML.
По умолчанию HTML игнорирует переносы строк в коде, превращая их в пробелы. Однако CSS-свойство white-space позволяет изменить это поведение. Рассмотрим пример:
// В блоке стилей или атрибуте style задаем режим сохранения переносов
парДок = док.СоздатьЭлемент("h1");
парДок.УстановитьАтрибут("style", "white-space: pre-line;");
// Теперь Символы.ПС будут интерпретироваться как реальные переносы строк
парДок.ТекстовоеСодержимое = "" + Объект.Номер + Символы.ПС + Формат(Объект.Дата, "ДФ=dd.MM.yyyy");
телДок.ДобавитьДочерний(парДок);
Значение pre-line заставляет браузер схлопывать лишние пробелы, но сохранять символы перевода строки, что идеально подходит для нашей задачи.
Рассмотрим вариант, который часто используется как "быстрое решение" (или костыль), если работа с деревом DOM по каким-то причинам затруднена. Суть метода заключается во вставке уникального текстового маркера, который гарантированно не встретится в данных, с последующей заменой его на тег br уже в готовой строке HTML.
Посмотрим на логику реализации:
// Вставляем маркер
парДок.ТекстовоеСодержимое = "" + Объект.Номер + " _BREAK_HERE_ " + Объект.Дата;
// После того как весь документ сформирован и получен в виде строки
ТекстHTML = ТекстЗаписиHTML.ПолучитьТекст();
ТекстHTML = СтрЗаменить(ТекстHTML, " _BREAK_HERE_ ", "<br/>");
Важное предостережение: Будьте осторожны при использовании метода СтрЗаменить к итоговому тексту HTML. Если вы попытаетесь заменить просто < на <, вы рискуете повредить всю структуру документа, если эти сущности использовались в тексте намеренно.
Проанализировав все варианты, мы рекомендуем придерживаться следующей логики:
При использовании ЗаписьHTML также обратите внимание на метод ЗаписатьТекст(). У него есть второй параметр ЭкранироватьСпецСимволы. Если установить его в значение Ложь, система пропустит текст как есть, но в этом случае ответственность за валидность HTML-кода полностью ложится на разработчика.