ОболочкаHTMLДокумента.ПолучитьДокументHTML

Методы · GetHTMLDocument

Получает исходный HTML-документ в виде дерева DOM и объекта ДокументHTML.

Синтаксис

ПолучитьДокументHTML()
Полное описание, параметры и ограничения

ОболочкаHTMLДокумента.ПолучитьДокументHTML (HTMLDocumentShell.GetHTMLDocument)

ОболочкаHTMLДокумента (HTMLDocumentShell)

ПолучитьДокументHTML (GetHTMLDocument)

Доступен, начиная с версии 8.2.

Синтаксис:
ПолучитьДокументHTML()
Возвращаемое значение:
Тип: ДокументHTML.

Описание:

Получает исходный HTML-документ в виде дерева DOM и объекта ДокументHTML.

Доступность:

Сервер, толстый клиент, внешнее соединение.

Использование в версии:

Доступен, начиная с версии 8.2.

Методическая информация

Практические примеры

Свой HTML-счет в памяти: полный readback1050 и реальные текстовые сегменты статуса

Получаем свой compiled HTML через настоящую оболочку, читаем две строки и восемь ячеек, переносим только собственные сегменты атрибута проверки и нормализуем их без изменения товара или суммы. Исходный GetText не является сериализацией измененного DOM.

Где и как запускать

Платформа8.5.1.1343; серверный общий модуль своей новой File CF; управляемая форма только отображает скалярный протокол. Runtime1C/CF/UI не выполнялись.

Подготовка

  1. Задача: проверить две строки своего учебного счета в HTML-памяти и изменить только служебный статус проверки. BOOK3×250=750, TEA2×150=300: всего5 единиц и1050. Полный readback всех8 значений выполняется до изменения и после каждого шага. HTML-источник и измененное DOM-дерево — разные вещи.

  2. Вручную создайте НОВУЮ пустую файловую CF только C:\1c-labs\OwnHTMLInvoice85_45b60ceb-dc56-4b6d-8b97-b09e4ff31d42\IB. Имя конфигурации УчебныйHTMLСчет85, РежимСовместимостиНеИспользовать, основное приложениеУправляемоеПриложение. Windows8.5.1.1343, толстый управляемый клиент. Путь/имя/версия проверяются точно; иной формат native строки подключения откажет без fuzzy fallback. UUID в имени папки — маркер лаборатории, не UUID ИБ.

  3. Создайте единственную свою роль HTML85Администратор с полными правами только этой пустой CF, включая администрирование для native ПолучитьПользователей. Создайте единственного собственного пользователя HTML85Ученик и назначьте роль. Код берет настоящий ТекущийПользователь и проверяет UUID Users[0] только после Count1; никаких placeholders UUID пользователя и операций создания/записи пользователя нет. Не используйте рабочую УТ/КА/УНФ/БП, не подключайте расширения. Эти действия здесь не выполнялись.

  4. Конфигурация→Языки: оставьте ровно один язык Русский с кодом ru; ОсновнойЯзыкРусский. Общие→ОбщиеМакеты→Добавить НакладнаяHTML85 типаHTMLДокумент. В штатном редакторе HTML вручную вставьте весь visible supporting module НакладнаяHTML85 как одну строку без дополнительных переводов строк или editor-generated разметки. Это исходник собственного compiled макета, не URL/файл для сетевого чтения. GetText требует точное совпадение с этим образцом, не исправляет чужой или переформатированный HTML.

  5. Общие→ОбщиеМодули→СчетHTMLПамять85. СерверДа, Клиент(управляемое приложение)Нет, Клиент(обычное приложение)Нет, ГлобальныйНет, ВызовСервераНет, ПривилегированныйНет. Вставьте целиком CODE. Серверная процедура формы вызывает модуль в своем server context. Shell.КодЯзыкаМакета доступно только сервер/внешнее соединение: его не читает и не устанавливает клиент.

  6. Общие→ОбщиеФормы→ПроверкаСчетаHTML85, управляемая форма без основного реквизита. Реквизиты Количество85/Сумма85 — Число12,0; Статус85Строка20; Протокол85Строка неограниченной длины; Остановка85/Завершено85Булево, начальные False. Первые4 разместите как readonly поля, без HTML-поля/браузера; два флага не показывайте пользователю. Единственная команда Проверить85, ДействиеПроверить85(Команда), кнопка с КомандаПроверить85. В модуль формы вставьте FORM целиком.

  7. Конфигурация→Открыть модуль управляемого приложения: APPLICATION целиком. Реальное ПриНачалеРаботыСистемы() без параметров открывает только own common form, UniqueTrue не ищет прежнюю форму. Событие вручную не вызывается. Ни один HTML DOM объект не передается клиенту: только количество, сумма, полный текстовый снимок и статус после native server readback.

  8. После будущей ручной проверки синтаксиса, сохранения CF и обновления именно своей учебной ИБ запустите толстый управляемый клиент и нажмите Проверить85 один раз. Ожидаемый протокол: BOOK|3|250|750;TEA|2|150|300;, количество5, сумма1050, статусVERIFIED. Второй клик отвергается после успеха; после ошибки локальный и серверный sticky flags запрещают повтор и слепую очистку.

  9. Пример не вызывает CreateTextNode/CreateComment и не маскирует TextDOM под TextHTML. Value setter своего нового Attribute создает текстового ребенка; настоящий ChildNodes.Item возвращает union с TextHTML. Перед каждым native перемещением exact type, Count и own OwnerDocument подтверждаются. Если реализация выдала другой тип/неожиданное число детей, работа останавливается: runtime принадлежность не выдается за измеренную здесь.

  10. Для собственного status siblingPrev/siblingNext проверяются до изменений и после каждого шага. Ожидаем Undefined на этом подготовленном атрибуте; другое состояние вызывает отказ, а не обход строк по sibling атрибута. Это проверка конкретной границы own attribute, не универсальная гарантия реализации. Text.ParentNode вообще не применяется для доказательства типа родителя: native declared return неоднозначен. Членство доказывается own Attr.ChildNodes.Item identity.

  11. Отдельные будущие ручные отрицательные подготовки выполняйте только в НОВОМ собственном сеансе: лишняя третья строка, измененная цена/сумма, другой шаблон, незнакомый actual node type, TextDOM вместо ожидаемого TextHTML, неизвестный язык или wrong file registration. Любая ошибка завершает процесс; автоматического восстановления DOM/language после частичного отказа нет. Новая подготовленная сессия нужна вместо retry.

Процедура ПроверитьСвойСтенд85() Экспорт
    Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnHTMLInvoice85_45b60ceb-dc56-4b6d-8b97-b09e4ff31d42\IB"";" Тогда
        ВызватьИсключение "Нужен только свой точно подготовленный File-стенд 8.5.1.1343";
    КонецЕсли;
    Если Метаданные.ОбщиеМакеты.Количество() <> 1 Или Метаданные.ОбщиеМакеты.Найти("НакладнаяHTML85") = Неопределено
        Или Метаданные.ОбщиеМодули.Количество() <> 1 Или Метаданные.ОбщиеМодули.Найти("СчетHTMLПамять85") = Неопределено
        Или Метаданные.ОбщиеФормы.Количество() <> 1 Или Метаданные.ОбщиеФормы.Найти("ПроверкаСчетаHTML85") = Неопределено
        Или Метаданные.Языки.Количество() <> 1 Или Метаданные.Языки.Найти("Русский") = Неопределено Тогда
        ВызватьИсключение "Нужны ровно свои общий HTML-макет, модуль, форма и язык Русский с кодом ru";
    КонецЕсли;
    Язык = Метаданные.Языки.Найти("Русский");
    Если Язык.КодЯзыка <> "ru" Тогда
        ВызватьИсключение "Настоящий собственный язык конфигурации должен иметь код ru";
    КонецЕсли;
    Если Метаданные.Справочники.Количество() <> 0 Или Метаданные.Документы.Количество() <> 0
        Или Метаданные.РегистрыСведений.Количество() <> 0 Или Метаданные.РегистрыНакопления.Количество() <> 0
        Или Метаданные.РегистрыБухгалтерии.Количество() <> 0 Или Метаданные.РегистрыРасчета.Количество() <> 0 Тогда
        ВызватьИсключение "Не запускайте урок в конфигурации с прикладными объектами или данными";
    КонецЕсли;
    Если РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.БазаДанных).Количество() <> 0
        Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансАктивные).Количество() <> 0
        Или РасширенияКонфигурации.Получить(, ИсточникРасширенийКонфигурации.СеансОтключенные).Количество() <> 0 Тогда
        ВызватьИсключение "Только свой стенд без расширений";
    КонецЕсли;
    Текущий = ПользователиИнформационнойБазы.ТекущийПользователь();
    Пользователи = ПользователиИнформационнойБазы.ПолучитьПользователей();
    Если Текущий = Неопределено Или Пользователи.Количество() <> 1 Тогда
        ВызватьИсключение "Нужен единственный реальный собственный пользователь ИБ";
    КонецЕсли;
    Если Текущий.Имя <> "HTML85Ученик" Или Пользователи[0].УникальныйИдентификатор <> Текущий.УникальныйИдентификатор Тогда
        ВызватьИсключение "Не совпала реальная идентичность собственного пользователя ИБ";
    КонецЕсли;
КонецПроцедуры

Функция ИсходныйHTML85()
    Возврат "<html><head><title>Свой счет85</title></head><body><div data-own=""45b60ceb-dc56-4b6d-8b97-b09e4ff31d42"" data-status=""DRAFT""><table><tbody><tr><td>BOOK</td><td>3</td><td>250</td><td>750</td></tr><tr><td>TEA</td><td>2</td><td>150</td><td>300</td></tr></tbody></table></div></body></html>";
КонецФункции

Процедура ПроверитьИсточник85(Оболочка, Исходник)
    Если ТипЗнч(Оболочка) <> Тип("ОболочкаHTMLДокумента") Или ТипЗнч(Исходник) <> Тип("Строка")
        Или Исходник <> ИсходныйHTML85() Или Оболочка.ПолучитьТекст() <> Исходник Тогда
        ВызватьИсключение "Исходный текст собственного compiled HTML-макета отличается от видимого образца";
    КонецЕсли;
КонецПроцедуры

Процедура НайтиСвоиУзлы85(Узел, Документ, Найденные, Глубина, Посещено)
    Посещено = Посещено + 1;
    Если Глубина > 12 Или Посещено > 64 Тогда
        ВызватьИсключение "Слишком большое или неожиданное собственное дерево";
    КонецЕсли;
    Если ТипЗнч(Узел) = Тип("ТекстHTML") Тогда
        Если Не Узел.ДокументВладелец.УзелИдентичен(Документ) Тогда
            ВызватьИсключение "Текст принадлежит другому HTML-документу";
        КонецЕсли;
        Возврат;
    КонецЕсли;
    Если ТипЗнч(Узел) <> Тип("ЭлементHTML") И ТипЗнч(Узел) <> Тип("ЭлементБлокHTML")
        И ТипЗнч(Узел) <> Тип("ЭлементТаблицаHTML") И ТипЗнч(Узел) <> Тип("ЭлементСтрокаТаблицыHTML")
        И ТипЗнч(Узел) <> Тип("ЭлементЯчейкаТаблицыHTML") Тогда
        ВызватьИсключение "Actual parsed узел не входит в точный whitelist нашего HTML";
    КонецЕсли;
    Если ТипЗнч(Узел.ДокументВладелец) <> Тип("ДокументHTML") Или Не Узел.ДокументВладелец.УзелИдентичен(Документ) Тогда
        ВызватьИсключение "В parsed дереве обнаружен другой документ-владелец";
    КонецЕсли;
    Имя = ВРег(Узел.ИмяЭлемента);
    Если Имя <> "HTML" И Имя <> "HEAD" И Имя <> "TITLE" И Имя <> "BODY" И Имя <> "DIV"
        И Имя <> "TABLE" И Имя <> "TBODY" И Имя <> "TR" И Имя <> "TD" Тогда
        ВызватьИсключение "Неожиданный тег: не допускаем scripts, links, images, frames или формы";
    КонецЕсли;
    Если Имя = "DIV" Тогда
        Если ТипЗнч(Узел) <> Тип("ЭлементБлокHTML") Или Найденные.Блок <> Неопределено
            Или Узел.Атрибуты.Количество() <> 2 Или Узел.ПолучитьАтрибут("data-own") <> "45b60ceb-dc56-4b6d-8b97-b09e4ff31d42" Тогда
            ВызватьИсключение "Не найден единственный настоящий собственный DIV";
        КонецЕсли;
        Найденные.Блок = Узел;
    ИначеЕсли Имя = "TABLE" Тогда
        Если ТипЗнч(Узел) <> Тип("ЭлементТаблицаHTML") Или Найденные.Таблица <> Неопределено Или Узел.Атрибуты.Количество() <> 0 Тогда
            ВызватьИсключение "Не найдена единственная настоящая таблица собственного счета";
        КонецЕсли;
        Найденные.Таблица = Узел;
    КонецЕсли;
    Дети = Узел.ДочерниеУзлы;
    Если ТипЗнч(Дети) <> Тип("СписокУзловHTML") Тогда
        ВызватьИсключение "ChildNodes не вернул собственный native HTMLNodeList";
    КонецЕсли;
    Для Индекс = 0 По Дети.Количество() - 1 Цикл
        Ребенок = Дети.Элемент(Индекс);
        НайтиСвоиУзлы85(Ребенок, Документ, Найденные, Глубина + 1, Посещено);
    КонецЦикла;
КонецПроцедуры

Функция ПрочитатьВсеСтроки85(Таблица, Документ)
    Если ТипЗнч(Таблица) <> Тип("ЭлементТаблицаHTML") Или Не Таблица.ДокументВладелец.УзелИдентичен(Документ) Тогда
        ВызватьИсключение "Нужна настоящая таблица собственного parsed документа";
    КонецЕсли;
    Строки = Таблица.ПолучитьСтроки();
    Если ТипЗнч(Строки) <> Тип("КоллекцияЭлементовHTML") Или Строки.Количество() <> 2 Тогда
        ВызватьИсключение "Требуются ровно две реальные строки счета";
    КонецЕсли;
    ВсегоКоличество = 0;
    ВсегоСумма = 0;
    Снимок = "";
    Для Номер = 0 По 1 Цикл
        СтрокаHTML = Строки.Элемент(Номер);
        Если ТипЗнч(СтрокаHTML) <> Тип("ЭлементСтрокаТаблицыHTML")
            Или Не СтрокаHTML.ДокументВладелец.УзелИдентичен(Документ) Тогда
            ВызватьИсключение "Не получена настоящая собственная строка HTML";
        КонецЕсли;
        Ячейки = СтрокаHTML.Ячейки;
        Если ТипЗнч(Ячейки) <> Тип("КоллекцияЭлементовHTML") Или Ячейки.Количество() <> 4 Тогда
            ВызватьИсключение "В каждой собственной строке нужны товар, количество, цена и сумма";
        КонецЕсли;
        Значения = Новый Массив;
        Для Колонка = 0 По 3 Цикл
            Ячейка = Ячейки.Элемент(Колонка);
            Если ТипЗнч(Ячейка) <> Тип("ЭлементЯчейкаТаблицыHTML")
                Или Не Ячейка.ДокументВладелец.УзелИдентичен(Документ) Тогда
                ВызватьИсключение "Не получена настоящая собственная ячейка HTML";
            КонецЕсли;
            Текст = Ячейка.ТекстовоеСодержимое;
            Если ТипЗнч(Текст) <> Тип("Строка") Тогда
                ВызватьИсключение "Ячейка не содержит actual строковый текст";
            КонецЕсли;
            Значения.Добавить(Текст);
        КонецЦикла;
        Если Значения[0] <> ?(Номер = 0, "BOOK", "TEA") Или Значения[1] <> ?(Номер = 0, "3", "2")
            Или Значения[2] <> ?(Номер = 0, "250", "150") Или Значения[3] <> ?(Номер = 0, "750", "300") Тогда
            ВызватьИсключение "Изменено хотя бы одно из всех восьми собственных значений";
        КонецЕсли;
        Количество = Число(Значения[1]);
        Цена = Число(Значения[2]);
        СуммаСтроки = Число(Значения[3]);
        Если Количество * Цена <> СуммаСтроки Тогда
            ВызватьИсключение "Числовая сумма реальной строки не равна количеству на цену";
        КонецЕсли;
        ВсегоКоличество = ВсегоКоличество + Количество;
        ВсегоСумма = ВсегоСумма + СуммаСтроки;
        Снимок = Снимок + Значения[0] + "|" + Значения[1] + "|" + Значения[2] + "|" + Значения[3] + ";";
    КонецЦикла;
    Если ВсегоКоличество <> 5 Или ВсегоСумма <> 1050 Тогда
        ВызватьИсключение "Полный native readback не подтвердил количество5 и сумму1050";
    КонецЕсли;
    Возврат Новый ФиксированнаяСтруктура("Количество,Сумма,Снимок", ВсегоКоличество, ВсегоСумма, Снимок);
КонецФункции

Процедура ПроверитьСвойСтатус85(Атрибут, Блок, Документ, Значение, ЧислоДетей)
    Если ТипЗнч(Атрибут) <> Тип("АтрибутHTML") Или Атрибут.Имя <> "data-status"
        Или Не Атрибут.ДокументВладелец.УзелИдентичен(Документ)
        Или Не Атрибут.ЭлементВладелец.УзелИдентичен(Блок)
        Или Не Блок.ПолучитьУзелАтрибута("data-status").УзелИдентичен(Атрибут)
        Или Атрибут.Значение <> Значение Или Блок.ПолучитьАтрибут("data-status") <> Значение Тогда
        ВызватьИсключение "Собственный атрибут статуса, его владельцы или значение изменены";
    КонецЕсли;
    Предыдущий = Атрибут.ПредыдущийСоседний;
    Следующий = Атрибут.СледующийСоседний;
    Если Предыдущий <> Неопределено Или Следующий <> Неопределено Тогда
        ВызватьИсключение "Для нашего собственного атрибута не подтверждена граница: не обходите товары по sibling атрибута";
    КонецЕсли;
    ДетиАтрибута = Атрибут.ДочерниеУзлы;
    Если ТипЗнч(ДетиАтрибута) <> Тип("СписокУзловHTML") Или ДетиАтрибута.Количество() <> ЧислоДетей Тогда
        ВызватьИсключение "Не совпало фактическое число собственных текстовых сегментов статуса";
    КонецЕсли;
    Собранный = "";
    Для Индекс = 0 По ДетиАтрибута.Количество() - 1 Цикл
        Текстовый = ДетиАтрибута.Элемент(Индекс);
        Если ТипЗнч(Текстовый) <> Тип("ТекстHTML") Или Не Текстовый.ДокументВладелец.УзелИдентичен(Документ) Тогда
            ВызватьИсключение "Actual child не является собственным TextHTML; TextDOM не переименовываем в HTML";
        КонецЕсли;
        Собранный = Собранный + Текстовый.Данные;
    КонецЦикла;
    Если Собранный <> Значение Тогда
        ВызватьИсключение "Значение атрибута не совпало с прочитанными actual текстовыми сегментами";
    КонецЕсли;
КонецПроцедуры

Функция ПодготовитьСвойФрагмент85(Документ, Имя, Данные)
    Если Имя <> "own-prefix85" И Имя <> "own-suffix85" И Имя <> "own-replacement85" Тогда
        ВызватьИсключение "Разрешены только три новых собственных буфера статуса";
    КонецЕсли;
    Буфер = Документ.СоздатьАтрибут(Имя);
    Если ТипЗнч(Буфер) <> Тип("АтрибутHTML") Или Буфер.Имя <> Имя Или Не Буфер.ДокументВладелец.УзелИдентичен(Документ) Тогда
        ВызватьИсключение "Native CreateAttribute не вернул собственный атрибут того же документа";
    КонецЕсли;
    Буфер.Значение = Данные;
    Если Буфер.Значение <> Данные Или Буфер.ДочерниеУзлы.Количество() <> 1 Тогда
        ВызватьИсключение "Native Value setter не подготовил один собственный текстовый сегмент";
    КонецЕсли;
    Возврат Буфер;
КонецФункции

Функция ПолучитьСвойТекст85(Буфер, Документ, Данные)
    Если ТипЗнч(Буфер) <> Тип("АтрибутHTML") Или Буфер.ДочерниеУзлы.Количество() <> 1
        Или Не Буфер.ДокументВладелец.УзелИдентичен(Документ) Или Буфер.Значение <> Данные Тогда
        ВызватьИсключение "Не подтвержден полностью собственный односегментный буфер";
    КонецЕсли;
    Текстовый = Буфер.ДочерниеУзлы.Элемент(0);
    Если ТипЗнч(Текстовый) <> Тип("ТекстHTML") Или Не Текстовый.ДокументВладелец.УзелИдентичен(Документ)
        Или Текстовый.Данные <> Данные Или Не Буфер.ДочерниеУзлы.Элемент(0).УзелИдентичен(Текстовый) Тогда
        ВызватьИсключение "Настоящий ChildNodes.Item не вернул ожидаемый TextHTML этого буфера";
    КонецЕсли;
    Возврат Текстовый;
КонецФункции

Процедура ПроверитьПослеШага85(Оболочка, Исходник, Документ, Блок, Таблица, Атрибут, Значение, ЧислоДетей, До)
    ПроверитьИсточник85(Оболочка, Исходник);
    ПроверитьСвойСтатус85(Атрибут, Блок, Документ, Значение, ЧислоДетей);
    Сейчас = ПрочитатьВсеСтроки85(Таблица, Документ);
    Если Сейчас.Количество <> До.Количество Или Сейчас.Сумма <> До.Сумма Или Сейчас.Снимок <> До.Снимок Тогда
        ВызватьИсключение "Хотя бы одна исходная строка или полный числовой итог изменены";
    КонецЕсли;
КонецПроцедуры

Функция ВыполнитьСвойУрок85() Экспорт
    ПроверитьСвойСтенд85();
    Оболочка = ПолучитьОбщийМакет("НакладнаяHTML85");
    Если ТипЗнч(Оболочка) <> Тип("ОболочкаHTMLДокумента") Тогда
        ВызватьИсключение "Свой макет должен быть именно compiled HTMLДокумент, не строка и не новый Document";
    КонецЕсли;
    ИсходныйЯзык = Оболочка.КодЯзыкаМакета;
    Если ИсходныйЯзык <> Неопределено И ИсходныйЯзык <> "ru" Тогда
        ВызватьИсключение "Исходная локализация собственного макета неожиданна; чужой профиль не меняем";
    КонецЕсли;
    Исходник = Оболочка.ПолучитьТекст();
    ПроверитьИсточник85(Оболочка, Исходник);
    Оболочка.КодЯзыкаМакета = "ru";
    Если Оболочка.КодЯзыкаМакета <> "ru" Тогда
        ВызватьИсключение "Native language setter не подтвердил собственный ru";
    КонецЕсли;
    ПроверитьИсточник85(Оболочка, Исходник);
    Документ = Оболочка.ПолучитьДокументHTML();
    Если ТипЗнч(Документ) <> Тип("ДокументHTML") Тогда
        ВызватьИсключение "Native shell getter не вернул настоящий parsed ДокументHTML";
    КонецЕсли;
    Корень = Документ.ЭлементДокумента;
    Если ТипЗнч(Корень) <> Тип("ЭлементHTML") Тогда
        ВызватьИсключение "Native DocumentElement не вернул собственный корневой HTMLElement";
    КонецЕсли;
    Найденные = Новый Структура("Блок,Таблица");
    Посещено = 0;
    НайтиСвоиУзлы85(Корень, Документ, Найденные, 0, Посещено);
    Если Найденные.Блок = Неопределено Или Найденные.Таблица = Неопределено Тогда
        ВызватьИсключение "Свой DIV и таблица не найдены в actual parsed дереве";
    КонецЕсли;
    Блок = Найденные.Блок;
    Таблица = Найденные.Таблица;
    Атрибут = Блок.ПолучитьУзелАтрибута("data-status");
    ПроверитьСвойСтатус85(Атрибут, Блок, Документ, "DRAFT", 1);
    До = ПрочитатьВсеСтроки85(Таблица, Документ);
    ОригинальныйТекст = ПолучитьСвойТекст85(Атрибут, Документ, "DRAFT");
    Суффикс = ПодготовитьСвойФрагмент85(Документ, "own-suffix85", "ED");
    Префикс = ПодготовитьСвойФрагмент85(Документ, "own-prefix85", "CHECK");
    Замена = ПодготовитьСвойФрагмент85(Документ, "own-replacement85", "VERIFI");
    ТекстСуффикса = ПолучитьСвойТекст85(Суффикс, Документ, "ED");
    ТекстПрефикса = ПолучитьСвойТекст85(Префикс, Документ, "CHECK");
    ТекстЗамены = ПолучитьСвойТекст85(Замена, Документ, "VERIFI");
    Удаленный = Атрибут.УдалитьДочерний(ОригинальныйТекст);
    Если ТипЗнч(Удаленный) <> Тип("ТекстHTML") Или Не Удаленный.УзелИдентичен(ОригинальныйТекст) Тогда
        ВызватьИсключение "RemoveChild не вернул именно удаленный собственный текст";
    КонецЕсли;
    ПроверитьПослеШага85(Оболочка, Исходник, Документ, Блок, Таблица, Атрибут, "", 0, До);
    Добавленный = Атрибут.ДобавитьДочерний(ТекстСуффикса);
    Если ТипЗнч(Добавленный) <> Тип("ТекстHTML") Или Не Добавленный.УзелИдентичен(ТекстСуффикса) Или Суффикс.ДочерниеУзлы.Количество() <> 0 Тогда
        ВызватьИсключение "AppendChild не подтвердил перенос собственного суффикса";
    КонецЕсли;
    ПроверитьПослеШага85(Оболочка, Исходник, Документ, Блок, Таблица, Атрибут, "ED", 1, До);
    Вставленный = Атрибут.ВставитьПеред(ТекстПрефикса, ТекстСуффикса);
    Если ТипЗнч(Вставленный) <> Тип("ТекстHTML") Или Не Вставленный.УзелИдентичен(ТекстПрефикса)
        Или Префикс.ДочерниеУзлы.Количество() <> 0 Или Не Атрибут.ДочерниеУзлы.Элемент(0).УзелИдентичен(ТекстПрефикса) Тогда
        ВызватьИсключение "InsertBefore не подтвердил перенос и фактический порядок сегментов";
    КонецЕсли;
    ПроверитьПослеШага85(Оболочка, Исходник, Документ, Блок, Таблица, Атрибут, "CHECKED", 2, До);
    Замененный = Атрибут.ЗаменитьДочерний(ТекстЗамены, ТекстПрефикса);
    Если ТипЗнч(Замененный) <> Тип("ТекстHTML") Или Не Замененный.УзелИдентичен(ТекстПрефикса)
        Или Замена.ДочерниеУзлы.Количество() <> 0 Или Не Атрибут.ДочерниеУзлы.Элемент(0).УзелИдентичен(ТекстЗамены) Тогда
        ВызватьИсключение "ReplaceChild не вернул прежний сегмент и не подтвердил новый порядок";
    КонецЕсли;
    ПроверитьПослеШага85(Оболочка, Исходник, Документ, Блок, Таблица, Атрибут, "VERIFIED", 2, До);
    Атрибут.Нормализовать();
    ПроверитьПослеШага85(Оболочка, Исходник, Документ, Блок, Таблица, Атрибут, "VERIFIED", 1, До);
    Финал = ПрочитатьВсеСтроки85(Таблица, Документ);
    Если Оболочка.КодЯзыкаМакета <> "ru" Тогда
        ВызватьИсключение "Язык изменился: запрещено слепое восстановление чужого состояния";
    КонецЕсли;
    Оболочка.КодЯзыкаМакета = ИсходныйЯзык;
    Если Оболочка.КодЯзыкаМакета <> ИсходныйЯзык Тогда
        ВызватьИсключение "Исходный actual language baseline не восстановлен";
    КонецЕсли;
    ПроверитьИсточник85(Оболочка, Исходник);
    Возврат Новый ФиксированнаяСтруктура("Количество,Сумма,Снимок,Статус", Финал.Количество, Финал.Сумма, Финал.Снимок, Атрибут.Значение);
КонецФункции
Полный модуль своей управляемой формы: две границы fail-stop

Общие → Общие формы → ПроверкаСчетаHTML85 → Модуль

Толстый управляемый клиент и серверные процедуры своей формы; отдельные директивы контекста

&НаКлиенте
Процедура Проверить85(Команда)
#Если ТолстыйКлиентУправляемоеПриложение Тогда
    Если Остановка85 Или Завершено85 Или ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда <> Команды.Проверить85 Тогда
        ВызватьИсключение "Только одно выполнение своей команды: после успеха или ошибки новую попытку не делаем";
    КонецЕсли;
    Попытка
        ПроверитьНаСервере85();
        Если Не Завершено85 Или Количество85 <> 5 Или Сумма85 <> 1050 Или Статус85 <> "VERIFIED" Тогда
            ВызватьИсключение "Скалярный результат полного server native readback не подтвержден";
        КонецЕсли;
    Исключение
        Остановка85 = Истина;
        Протокол85 = "Отказ. Возможны частичные изменения только своего memory DOM; нет повтора, слепого сброса или очистки.";
        ВызватьИсключение;
    КонецПопытки;
#Иначе
    ВызватьИсключение "Своя форма только в толстом управляемом клиенте";
#КонецЕсли
КонецПроцедуры

&НаСервере
Процедура ПроверитьНаСервере85()
    Если Остановка85 Или Завершено85 Тогда
        ВызватьИсключение "Серверная граница также запрещает повтор";
    КонецЕсли;
    Попытка
        Пакет = СчетHTMLПамять85.ВыполнитьСвойУрок85();
        Если Пакет.Количество <> 5 Или Пакет.Сумма <> 1050 Или Пакет.Статус <> "VERIFIED"
            Или Пакет.Снимок <> "BOOK|3|250|750;TEA|2|150|300;" Тогда
            ВызватьИсключение "Native pipeline не вернул полный подтвержденный собственный счет";
        КонецЕсли;
        Количество85 = Пакет.Количество;
        Сумма85 = Пакет.Сумма;
        Статус85 = Пакет.Статус;
        Протокол85 = Пакет.Снимок + Символы.ПС + "DRAFT → пусто → ED → CHECKED → VERIFIED; Normalize2→1. Исходный HTML отдельно сохранен.";
        Завершено85 = Истина;
    Исключение
        Остановка85 = Истина;
        ВызватьИсключение;
    КонецПопытки;
КонецПроцедуры
Настоящее startup событие открывает только свою новую общую форму

Конфигурация → Открыть модуль управляемого приложения

Толстый клиент, управляемое приложение

Процедура ПриНачалеРаботыСистемы()
#Если ТолстыйКлиентУправляемоеПриложение Тогда
    Если Метаданные.РежимСовместимости <> Метаданные.СвойстваОбъектов.РежимСовместимости.НеИспользовать Или СтрокаСоединенияИнформационнойБазы() <> "File=""C:\1c-labs\OwnHTMLInvoice85_45b60ceb-dc56-4b6d-8b97-b09e4ff31d42\IB"";" Тогда
        ВызватьИсключение "Запускайте только свою новую File CF этого урока";
    КонецЕсли;
    ОткрытьФорму("ОбщаяФорма.ПроверкаСчетаHTML85", , , Истина);
#Иначе
    ВызватьИсключение "Только собственный толстый управляемый клиент 8.5.1.1343";
#КонецЕсли
КонецПроцедуры
Копируемый полный HTML-исходник собственного общего макета

Общие → Общие макеты → НакладнаяHTML85 → редактор HTML

Ручная подготовка общего compiled HTML макета ru, не исполняемый BSL и не браузер

<html><head><title>Свой счет85</title></head><body><div data-own="45b60ceb-dc56-4b6d-8b97-b09e4ff31d42" data-status="DRAFT"><table><tbody><tr><td>BOOK</td><td>3</td><td>250</td><td>750</td></tr><tr><td>TEA</td><td>2</td><td>150</td><td>300</td></tr></tbody></table></div></body></html>

Разбор по шагам

  1. Native GetCommonTemplate1 возвращает union: сначала реальный TypeShell guard. Original GetText0 сверяется с видимым HTML. CodeLanguage baseline допускает только Undefined/ru; свой ru задается только на сервере и читается обратно.

  2. Native Shell.GetHTMLDocument0 дает настоящий ДокументHTML; DocumentElement→actualChildNodes обход с ограничениями глубины/количества находит свой DIV и таблицу, без guessed GetElementById/списка DOM alias или жесткого индекса TBODY.

  3. Native Table.GetRows0 и Row.Cells читаются полностью: ровно2строки x4ячейки, все товары/qty/price/amount; число5/1050 вычисляется из actual прочитанного текста, а не возвращается из prepared golden вместо reader.

  4. Свой status проверяется по имени, OwnerDocument, OwnerElement и actual GetAttributeNode identity. Оба readonly sibling используются как guard границы статуса; строки берутся только настоящей коллекцией таблицы.

  5. Три новые собственные Attribute buffers держат CHECK, ED, VERIFI. Value setter создает текст, настоящий ChildNodes.Item0 с TypeTextHTML/OwnerDoc/identity проверяется до native перемещений. Никакого NewAttribute/NewHTMLText/CreateTextNode или подмены return aliases.

  6. Remove1 возвращает прежний DRAFT; Append1 переносит ED; Insert2 ставит CHECK передED; Replace2 возвращает старый CHECK и переноситVERIFI; Normalize0 оставляет VERIFIED и объединяет2→1actual child. После каждого шага источник и полный native numeric snapshot перечитываются.

  7. Язык восстанавливается только после полного verified success и guard текущего ru, именно к прочитанному baseline. GetText снова проверяет ORIGINAL source; возвращаемый final status читается с живого Attribute.Value, не из GetText и не из константы результата.

Как проверить результат

  1. Будущий manual native result: BOOK3×250=750; TEA2×150=300; qty5/total1050 до, на всех5шагах и после. Полный snapshot восьми ячеек одинаков.

  2. Actual status child counts1→0→1→2→2→1; значенияDRAFT→empty→ED→CHECKED→VERIFIED→VERIFIED. Возвращенные узлы проверяются по identity, исходные buffer children после перемещения0.

  3. Исходный compiled GetText точный и неизменный; живой statusVERIFIED проверяется отдельно. Нет обещания GetText serialization/HTML browser pixels/нормализации всего документа.

  4. Здесь native static signatures/context/readonly/factory scope и negative mutants; runtimeVerifiedFalse, реальная1С/CF/GUI/IB/network0.

Ожидаемый результат

Ожидаемый будущий ручной результат: две прежние строки, количество5, сумма1050 и живой native statusVERIFIED из одного текстового сегмента. Исходный HTML отдельно остается исходным, language baseline восстановлен после success. Этот runtime результат здесь не выполнялся.

На что обратить внимание

  1. Оболочка, АтрибутHTML и КомментарийHTML не имеют прямого ctor. ДокументHTML ctor имеет required title и не является parser HTML string; здесь он не используется.

  2. СоздатьТекстовыйУзел/СоздатьКомментарий объявляют DOM returns. Этот урок получает actualTextHTML только через documented native child list и требует его runtime type. Не превращайте literal alias/переменную в proof типа.

  3. TextHTML в установленной справке помечен не рекомендуемым с8.2: это точный ограниченный урок поддержки существующего HTML-макета. Не переносите его без проверки в современный браузерный DOM/API.

  4. Общий native CompareDocumentPosition не документирует result; COM getters и legacy Comment child/Text operations не кредитуются. Comment.Normalize leaf no-op не добавлен ради числа.

  5. Value setter уничтожает прежних детей только своего нового буфера. Дочерние методы перемещают реальные узлы, могут отказать при wrong owner/readonly/invalid child; partial mutation не атомарна. После исключения нет продолжения, automatic rollback/retry.

  6. Свойство язык выбирает локализацию для getter; typed readback ru не доказывает renderer/visual language. GetText остается исходным текстом, не export измененной DOM. Никаких DBwrites, печати, сети, COM или исполнения внешнего HTML.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.