Тип: АтрибутHTML, Неопределено. Следующий соседний узел HTML или Неопределено, если такового нет.
Полное описание, параметры и ограничения
АтрибутHTML.СледующийСоседний (HTMLAttribute.NextSibling)
АтрибутHTML (HTMLAttribute)
СледующийСоседний (NextSibling)
Доступен, начиная с версии 8.2.
Использование:
Только чтение.
Описание:
Тип: АтрибутHTML, Неопределено.
Следующий соседний узел HTML или Неопределено, если такового нет.
Доступность:
Тонкий клиент, мобильный клиент, сервер, толстый клиент, внешнее соединение, мобильное приложение (клиент), мобильное приложение (сервер), мобильный автономный сервер.
Использование в версии:
Доступен, начиная с версии 8.2.
Методическая информация
Практические примеры
Изменить три отделённые HTML-копии и сохранить настоящие оригиналы
Настоящие атрибут, текст и комментарий из своей строки копируются с проверкой реальных типов, паспорта, отдельных границ и пользовательских отметок. Меняем только копии на B-02, повторно читаем неизменные оригиналы A-01 и вычисляем сумму отметок 6.
Где и как запускать
Сервер; полный неглобальный непривилегированный общий модуль HTMLПаспорт85. Только собственная строка и память.
Подготовка
Будущий ручной опыт выполняйте в своей новой пустой учебной конфигурации на платформе 8.5.1.1343, в толстом управляемом клиенте. Здесь создаётся только собственное дерево из фиксированной строки в памяти; файлы, Интернет и объекты рабочей базы не используются.
Общие → Общие модули → создать HTMLПаспорт85. Сервер=Да; Глобальный=Нет; Привилегированный=Нет; Вызов сервера=Нет; оба клиентских флага=Нет; Внешнее соединение=Нет; повторное использование возвращаемых значений — Не использовать. Основной блок вставьте целиком в пустой модуль.
Общие → Общие формы → создать управляемую форму HTMLПаспорт85. Добавьте реквизит Результат85: Строка неограниченной длины; выведите многострочным полем только для чтения. Создайте команду Проверить85, Действие=Проверить85, выведите её кнопку.
У формы задайте АвтоматическоеСохранениеДанныхВНастройках=АвтоматическоеСохранениеДанныхФормыВНастройках.НеИспользовать и СохранениеДанныхВНастройках=СохранениеДанныхФормыВНастройках.НеИспользовать. Это два различных перечисления, не Булево. Не создавайте обработчики сохранения.
Второй блок — целый модуль формы HTMLПаспорт85. Третий — целый модуль общей команды ОткрытьHTMLПаспорт85 без параметра. Общую команду включите в командный интерфейс собственной учебной подсистемы. Штатные параметры обоих обработчиков передаёт платформа; вручную их не вызывайте.
Обновите конфигурацию собственной учебной базы, откройте форму общей командой и нажмите Проверить85. Разбор и изменения своих узлов выполняются на сервере; клиент получает только строку проверенного результата.
Специальные HTML-классы старого DOM и часть операций не рекомендуются начиная с 8.2. Это узкий урок сопровождения старого кода, не способ управлять браузером и не рекомендация для нового веб-интерфейса.
Этот код в 1С ещё не компилировался и не выполнялся. Неверный фактический тип, форма дерева, отказ операции или исключение означают остановку; сообщение об остановке не является успешным примером.
Функция ПрочитатьСвоюСтроку85(СтрокаHTML85)
Чтение = Новый ЧтениеHTML;
Если ТипЗнч(Чтение) <> Тип("ЧтениеHTML") Тогда
ВызватьИсключение "Не создано настоящее ЧтениеHTML";
КонецЕсли;
Попытка
Чтение.УстановитьСтроку(СтрокаHTML85);
Построитель = Новый ПостроительDOM;
Если ТипЗнч(Построитель) <> Тип("ПостроительDOM") Тогда
ВызватьИсключение "Не создан настоящий ПостроительDOM";
КонецЕсли;
Документ = Построитель.Прочитать(Чтение);
Исключение
Чтение.Закрыть();
ВызватьИсключение;
КонецПопытки;
Чтение.Закрыть();
Если ТипЗнч(Документ) <> Тип("ДокументHTML") Тогда
ВызватьИсключение "Не получен настоящий ДокументHTML";
КонецЕсли;
Возврат Документ;
КонецФункции
Функция НайтиСвойБлок85(Документ, Идентификатор85)
Блок85 = Документ.ПолучитьЭлементПоИдентификатору(Идентификатор85);
Если Блок85 = Неопределено Тогда
ВызватьИсключение "В своей строке не найден нужный div";
КонецЕсли;
Если ТипЗнч(Блок85) <> Тип("ЭлементБлокHTML")
Или Блок85.ДокументВладелец <> Документ Тогда
ВызватьИсключение "Нужен настоящий собственный ЭлементБлокHTML";
КонецЕсли;
Возврат Блок85;
КонецФункции
Функция Проверить85() Экспорт
Документ = ПрочитатьСвоюСтроку85("<html><head><title>Свои три узла</title></head><body><div id='triplet85' data-guide='A-01'>A-01<!--A-01--></div></body></html>");
Блок85 = НайтиСвойБлок85(Документ, "triplet85");
Атрибут85 = Блок85.ПолучитьУзелАтрибута("data-guide");
Если ТипЗнч(Атрибут85) <> Тип("АтрибутHTML")
Или ТипЗнч(Атрибут85.Значение) <> Тип("Строка") Или Атрибут85.Значение <> "A-01" Тогда
ВызватьИсключение "Не получен настоящий собственный атрибут";
КонецЕсли;
Владелец85 = Атрибут85.ЭлементВладелец;
Если ТипЗнч(Владелец85) <> Тип("ЭлементБлокHTML") Или Владелец85 <> Блок85 Тогда
ВызватьИсключение "Не подтверждён фактический владелец своего атрибута";
КонецЕсли;
Узлы85 = Блок85.ДочерниеУзлы;
Если ТипЗнч(Узлы85) <> Тип("СписокУзловHTML") Или Узлы85.Количество() <> 2 Тогда
ВызватьИсключение "Нужны собственные текст и комментарий, а не атрибут в списке детей";
КонецЕсли;
Текст85 = Узлы85.Элемент(0);
Пометка85 = Узлы85.Элемент(1);
Если ТипЗнч(Текст85) <> Тип("ТекстHTML")
Или ТипЗнч(Пометка85) <> Тип("КомментарийHTML")
Или Текст85.ЗначениеУзла <> "A-01" Или Пометка85.Данные <> "A-01"
Или Блок85.ТекстовоеСодержимое <> "A-01" Тогда
ВызватьИсключение "Не получена собственная типизированная тройка A-01";
КонецЕсли;
Отчет185 = ПроверитьКопию85(Атрибут85, Документ, 1);
Отчет285 = ПроверитьКопию85(Текст85, Документ, 2);
Отчет385 = ПроверитьКопию85(Пометка85, Документ, 3);
Отметка185 = Атрибут85.ПолучитьПользовательскиеДанные("own-html85-passport");
Отметка285 = Текст85.ПолучитьПользовательскиеДанные("own-html85-passport");
Отметка385 = Пометка85.ПолучитьПользовательскиеДанные("own-html85-passport");
Если ТипЗнч(Отметка185) <> Тип("Число") Или Отметка185 <> 1
Или ТипЗнч(Отметка285) <> Тип("Число") Или Отметка285 <> 2
Или ТипЗнч(Отметка385) <> Тип("Число") Или Отметка385 <> 3 Тогда
ВызватьИсключение "Не прочитаны реальные три отметки обработки";
КонецЕсли;
Итого85 = Отметка185 + Отметка285 + Отметка385;
Если Итого85 <> 6 Или Атрибут85.Значение <> "A-01"
Или Текст85.ЗначениеУзла <> "A-01" Или Пометка85.Данные <> "A-01"
Или Блок85.ТекстовоеСодержимое <> "A-01"
Или Блок85.ДочерниеУзлы.Количество() <> 2 Тогда
ВызватьИсключение "Копии изменили собственные оригиналы или итог отметок";
КонецЕсли;
Возврат Отчет185 + Символы.ПС + Отчет285 + Символы.ПС + Отчет385 + Символы.ПС
+ "Оригиналы A-01 сохранены; копии B-02 проверены; сумма отметок: " + Строка(Итого85);
КонецФункции
Функция ПроверитьКопию85(Узел85, Документ, Номер85)
Если ТипЗнч(Узел85) <> Тип("АтрибутHTML")
И ТипЗнч(Узел85) <> Тип("ТекстHTML")
И ТипЗнч(Узел85) <> Тип("КомментарийHTML") Тогда
ВызватьИсключение "Нужен один из трёх настоящих собственных видов узла";
КонецЕсли;
Имя85 = Узел85.ИмяУзла;
ТипУзла85 = Узел85.ТипУзла;
Значение85 = Узел85.ЗначениеУзла;
Содержимое85 = Узел85.ТекстовоеСодержимое;
ЛокальноеИмя85 = Узел85.ЛокальноеИмя;
Префикс85 = Узел85.Префикс;
Дети85 = Узел85.ДочерниеУзлы;
ЧислоДетей85 = Дети85.Количество();
ЕстьДети85 = Узел85.ЕстьДочерниеУзлы();
ЕстьАтрибуты85 = Узел85.ЕстьАтрибуты();
Если ТипЗнч(Имя85) <> Тип("Строка") Или ТипЗнч(Значение85) <> Тип("Строка")
Или Значение85 <> "A-01" Или ТипЗнч(Содержимое85) <> Тип("Строка")
Или ТипЗнч(Дети85) <> Тип("СписокУзловHTML")
Или ТипЗнч(ЧислоДетей85) <> Тип("Число")
Или ТипЗнч(ЕстьДети85) <> Тип("Булево") Или ЕстьДети85 <> (ЧислоДетей85 > 0)
Или ТипЗнч(ЕстьАтрибуты85) <> Тип("Булево") Или ЕстьАтрибуты85
Или Узел85.Атрибуты <> Неопределено Или Узел85.ДокументВладелец <> Документ Тогда
ВызватьИсключение "Исходный фактический паспорт не соответствует своему узлу";
КонецЕсли;
Если ТипЗнч(Узел85) = Тип("АтрибутHTML") Тогда
Если ЧислоДетей85 < 0 Или ЧислоДетей85 > 1 Тогда
ВызватьИсключение "Не поддержана фактическая форма значения атрибута";
КонецЕсли;
Если ЧислоДетей85 = 1 Тогда
Ребенок85 = Дети85.Элемент(0);
Если ТипЗнч(Ребенок85) <> Тип("ТекстHTML") Или Ребенок85.ЗначениеУзла <> "A-01" Тогда
ВызватьИсключение "Не прочитан настоящий текстовый ребёнок атрибута";
КонецЕсли;
КонецЕсли;
Иначе
Если ЧислоДетей85 <> 0 Или Префикс85 <> Неопределено Тогда
ВызватьИсключение "Текст и комментарий должны быть листовыми узлами без префикса";
КонецЕсли;
КонецЕсли;
СтарыеДанные85 = Узел85.УстановитьПользовательскиеДанные("own-html85-passport", Номер85);
Если СтарыеДанные85 <> Неопределено
Или Узел85.ПолучитьПользовательскиеДанные("own-html85-passport") <> Номер85 Тогда
ВызватьИсключение "Собственная новая отметка не установлена";
КонецЕсли;
Копия85 = Узел85.КлонироватьУзел(Истина);
Если ТипЗнч(Копия85) <> ТипЗнч(Узел85) Тогда
ВызватьИсключение "Копия не имеет фактический исходный тип HTML";
КонецЕсли;
РавенДо85 = Узел85.УзелРавен(Копия85);
Идентичен85 = Узел85.УзелИдентичен(Копия85);
Если ТипЗнч(РавенДо85) <> Тип("Булево") Или Не РавенДо85
Или ТипЗнч(Идентичен85) <> Тип("Булево") Или Идентичен85
Или Копия85.РодительскийУзел <> Неопределено
Или Копия85.ПредыдущийСоседний <> Неопределено
Или Копия85.СледующийСоседний <> Неопределено
Или Копия85.ПолучитьПользовательскиеДанные("own-html85-passport") <> Неопределено Тогда
ВызватьИсключение "Не подтверждена настоящая отдельная копия без отметок";
КонецЕсли;
Если Копия85.ИмяУзла <> Имя85 Или Копия85.ТипУзла <> ТипУзла85
Или Копия85.ЗначениеУзла <> Значение85 Или Копия85.ТекстовоеСодержимое <> Содержимое85
Или Копия85.ЛокальноеИмя <> ЛокальноеИмя85 Или Копия85.Префикс <> Префикс85
Или Копия85.Атрибуты <> Неопределено Или Копия85.ДокументВладелец <> Документ
Или Копия85.ДочерниеУзлы.Количество() <> ЧислоДетей85
Или Копия85.ЕстьДочерниеУзлы() <> ЕстьДети85 Или Копия85.ЕстьАтрибуты() <> ЕстьАтрибуты85 Тогда
ВызватьИсключение "Повторное чтение копии не совпало с фактическим паспортом";
КонецЕсли;
Дополнение85 = "";
Если ТипЗнч(Копия85) = Тип("АтрибутHTML") Тогда
АтрибутКопия85 = Копия85;
АтрибутКопия85.Значение = "B-02";
НовыеДети85 = АтрибутКопия85.ДочерниеУзлы;
Если ТипЗнч(НовыеДети85) <> Тип("СписокУзловHTML") Или НовыеДети85.Количество() <> 1 Тогда
ВызватьИсключение "Запись значения копии не создала один настоящий текстовый узел";
КонецЕсли;
НовыйТекст85 = НовыеДети85.Элемент(0);
Если ТипЗнч(НовыйТекст85) <> Тип("ТекстHTML") Или НовыйТекст85.ЗначениеУзла <> "B-02"
Или АтрибутКопия85.Значение <> "B-02" Тогда
ВызватьИсключение "Не подтверждено новое значение только копии атрибута";
КонецЕсли;
Дополнение85 = "Детей атрибута до: " + Строка(ЧислоДетей85)
+ "; после изменения копии: " + Строка(НовыеДети85.Количество());
Иначе
ЛистоваяКопия85 = Копия85;
Если ЛистоваяКопия85.ДочерниеУзлы.Количество() <> 0
Или ЛистоваяКопия85.ПервыйДочерний <> Неопределено
Или ЛистоваяКопия85.ПоследнийДочерний <> Неопределено Тогда
ВызватьИсключение "Листовая копия неожиданно имеет детей";
КонецЕсли;
ЛистоваяКопия85.ЗначениеУзла = "B-02";
Пробелы85 = ЛистоваяКопия85.ЭтоПробельныеСимволыЭлемента;
Если ТипЗнч(Пробелы85) <> Тип("Булево") Тогда
ВызватьИсключение "Не получен фактический признак пробельного текста";
КонецЕсли;
Дополнение85 = "Признак пробелов: " + Строка(Пробелы85);
Если ТипЗнч(ЛистоваяКопия85) = Тип("КомментарийHTML") Тогда
КопияПометки85 = ЛистоваяКопия85;
ПолныйПометки85 = КопияПометки85.ПолныйТекст;
Если ТипЗнч(ПолныйПометки85) <> Тип("Строка") Тогда
ВызватьИсключение "Не прочитан фактический полный текст копии комментария";
КонецЕсли;
Дополнение85 = Дополнение85 + "; фактический полный текст: " + ПолныйПометки85;
КонецЕсли;
КонецЕсли;
РавенПосле85 = Узел85.УзелРавен(Копия85);
Если ТипЗнч(РавенПосле85) <> Тип("Булево") Или РавенПосле85
Или Копия85.ЗначениеУзла <> "B-02" Или Узел85.ЗначениеУзла <> Значение85
Или Узел85.ИмяУзла <> Имя85 Или Узел85.ТипУзла <> ТипУзла85
Или Узел85.ТекстовоеСодержимое <> Содержимое85
Или Узел85.ЛокальноеИмя <> ЛокальноеИмя85 Или Узел85.Префикс <> Префикс85
Или Узел85.ДочерниеУзлы.Количество() <> ЧислоДетей85
Или Узел85.ПолучитьПользовательскиеДанные("own-html85-passport") <> Номер85 Тогда
ВызватьИсключение "Независимость изменённой копии от оригинала не подтверждена";
КонецЕсли;
Возврат "Узел " + Строка(Номер85) + ": имя=" + Имя85 + "; тип=" + Строка(ТипУзла85)
+ "; оригинал=" + Узел85.ЗначениеУзла + "; копия=" + Копия85.ЗначениеУзла
+ "; локальное имя=" + Строка(ЛокальноеИмя85) + "; префикс=" + Строка(Префикс85)
+ "; текст до=" + Содержимое85 + "; отметка=" + Строка(Узел85.ПолучитьПользовательскиеДанные("own-html85-passport"))
+ "; " + Дополнение85;
КонецФункцииЦелый модуль своей управляемой формы HTMLПаспорт85
Общие → Общие формы → HTMLПаспорт85 → пустой модуль. Вставить целиком; Результат85 — строка; Действие команды Проверить85 связано с обработчиком.
Клиент — настоящий обработчик команды; сервер — ПолучитьПротокол85НаСервере. По границе передаётся только строка.
&НаКлиенте
Процедура Проверить85(Команда)
Если ТипЗнч(Команда) <> Тип("КомандаФормы") Или Команда.Имя <> "Проверить85" Тогда
ВызватьИсключение "Нажмите настоящую собственную кнопку проверки";
КонецЕсли;
Результат85 = "";
Попытка
Получено85 = ПолучитьПротокол85НаСервере();
Если ТипЗнч(Получено85) <> Тип("Строка") Или Получено85 = "" Тогда
ВызватьИсключение "Сервер не вернул полный строковый протокол";
КонецЕсли;
Результат85 = Получено85;
Исключение
Результат85 = "Проверка НЕ завершена. Опыт остановлен.";
ВызватьИсключение;
КонецПопытки;
КонецПроцедуры
&НаСервере
Функция ПолучитьПротокол85НаСервере()
Если ИмяФормы <> "ОбщаяФорма.HTMLПаспорт85"
Или АвтоматическоеСохранениеДанныхВНастройках <> АвтоматическоеСохранениеДанныхФормыВНастройках.НеИспользовать
Или СохранениеДанныхВНастройках <> СохранениеДанныхФормыВНастройках.НеИспользовать Тогда
ВызватьИсключение "Нужна своя форма с отключённым сохранением данных";
КонецЕсли;
Отчет85 = HTMLПаспорт85.Проверить85();
Если ТипЗнч(Отчет85) <> Тип("Строка") Или Отчет85 = "" Тогда
ВызватьИсключение "Собственный модуль не вернул полный протокол";
КонецЕсли;
Возврат Отчет85;
КонецФункцииЦелый модуль своей общей команды ОткрытьHTMLПаспорт85
Общие → Общие команды → ОткрытьHTMLПаспорт85 → пустой модуль. Без параметра; включить в собственный командный интерфейс.
Толстый управляемый клиент, &НаКлиенте. Настоящий ОбработкаКоманды с двумя штатными параметрами.
&НаКлиенте
Процедура ОбработкаКоманды(ПараметрКоманды, ПараметрыВыполненияКоманды)
#Если ТолстыйКлиентУправляемоеПриложение Тогда
Если ПараметрКоманды <> Неопределено
Или ТипЗнч(ПараметрыВыполненияКоманды) <> Тип("ПараметрыВыполненияКоманды") Тогда
ВызватьИсключение "Откройте свою форму штатной общей командой без параметра";
КонецЕсли;
ОткрытьФорму("ОбщаяФорма.HTMLПаспорт85");
#Иначе
ВызватьИсключение "Нужен толстый управляемый клиент";
#КонецЕсли
КонецПроцедурыРазбор по шагам
Своя строка содержит атрибут data-guide, видимый текст и комментарий со значением A-01. Атрибут получается через ПолучитьУзелАтрибута, а два ребёнка — из настоящего ограниченного списка; каждый специальный тип проверяется до его свойств.
Паспорт читает реальные имена, тип узла, значения, текст, локальное имя, префикс, число детей и признаки атрибутов. Эти данные сравниваются с копией и выводятся, а не подменяются именами #text/#comment или выдуманными пустыми пространствами имён.
Три настоящие отметки 1, 2 и 3 устанавливаются на исходных узлах. КлонироватьУзел(Истина) возвращает общий набор HTML-типов: у каждой фактической копии проверяется исходный тип, равенство содержания и отсутствие идентичности.
Копии не вставляются в дерево. Их фактические родитель, предыдущий и следующий сосед должны быть Неопределено; пользовательская отметка не копируется. Так изучаются отдельные копии, а не спорные соседние объекты разных классов.
Меняется только копия: Значение атрибута либо ЗначениеУзла текста/комментария становится B-02. У атрибута настоящий setter создаёт текстового ребёнка, который заново читается через широкий СписокУзловHTML и проверяется как ТекстHTML.
ПервыйДочерний и ПоследнийДочерний используются только у фактических листовых копий текста/комментария. У атрибута эти два свойства не демонстрируются: их объявленный тип АтрибутHTML не подтверждает текстового ребёнка.
После изменения родные узлы повторно читаются как A-01; копия уже не равна оригиналу, но это не повреждает исходную страницу. Отдельно читаются реальные три числовые отметки и вычисляется их сумма 6.
ПолныйТекст комментария и признак пробелов выводятся как фактические устаревшие наблюдения без обещания заранее известного значения. На клиент не передаются узлы, списки, перечисления или служебные данные — только строковый протокол.
Как проверить результат
Первый будущий запуск: три строки паспорта показывают реальные имена/типы; оригиналы остаются A-01, отдельные копии прочитаны как B-02, фактическая сумма отметок равна 6.
Проследите настоящие три типа до КлонироватьУзел, затем отдельный фактический тип каждой копии. До изменения равенство Истина, идентичность Ложь; после изменения равенство Ложь.
В отладчике у настоящих отделённых копий проверьте фактические Неопределено у родителя и соседей и отсутствие скопированных пользовательских отметок. Не прикрепляйте копии для искусственного исправления проверки.
У исходного атрибута допускается только измеренная форма 0/1 ребёнок. После записи значения копии должен быть один настоящий текстовый ребёнок B-02; исходный атрибут и страница не меняются.
Только в собственной копии уберите одну из проверок типа или подставьте прежний узел вместо результата клонирования: это отрицательный опыт, который не должен проходить контроль содержания и идентичности.
При неподдержанной фактической форме дерева или исключении нет успешного протокола. Состояние предыдущего отчёта очищается; ошибочный вызов не повторяется автоматически.
Ожидаемый результат
При полном успешном контроле: три реальные отдельные копии B-02, неизменные оригиналы A-01 и сумма трёх реально прочитанных отметок 6. Конкретные имена/полный текст устаревших свойств показываются как наблюдения.
На что обратить внимание
Модель создаётся только из собственной фиксированной строки. Нельзя подставлять внешний документ, объект пользователя, файл, URL или рабочие данные и считать этот пример проверкой их безопасности.
Установленная 8.5.1.1343 объявляет СоздатьКомментарий → КомментарийDOM и СоздатьТекстовыйУзел → ТекстDOM. Они не служат доказательством специальных HTML-получателей. Здесь реальные специальные узлы происходят из собственного HTMLReader/DOMBuilder и проверяются.
Общий возвращаемый HTML-тип не обещает конкретный класс в любой среде. Несовпадение фактического типа/формы означает остановку и неподтверждённый опыт, не успешный обход ошибки.
Не переносите правила имён, соседей и пространств имён из W3C по памяти. Сохраняются точные объявленные локальные контракты и реальные наблюдения; данные узлов не приводятся к другому классу.
Чтение закрывается на нормальном пути и в обработчике ошибки; исключение повторно вызывается. Ошибка самого закрытия тоже останавливает опыт: успешная очистка при любом отказе не обещается.
Нативные тексты справки и существующие конфигурационные образцы не исправлялись. Компилятор и 1С во время подготовки не запускались; статические проверки не являются выполнением примера.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.
Свой HTML-счет в памяти: полный readback1050 и реальные текстовые сегменты статуса
Получаем свой compiled HTML через настоящую оболочку, читаем две строки и восемь ячеек, переносим только собственные сегменты атрибута проверки и нормализуем их без изменения товара или суммы. Исходный GetText не является сериализацией измененного DOM.
Где и как запускать
Платформа8.5.1.1343; серверный общий модуль своей новой File CF; управляемая форма только отображает скалярный протокол. Runtime1C/CF/UI не выполнялись.
Подготовка
Задача: проверить две строки своего учебного счета в HTML-памяти и изменить только служебный статус проверки. BOOK3×250=750, TEA2×150=300: всего5 единиц и1050. Полный readback всех8 значений выполняется до изменения и после каждого шага. HTML-источник и измененное DOM-дерево — разные вещи.
Вручную создайте НОВУЮ пустую файловую CF только C:\1c-labs\OwnHTMLInvoice85_45b60ceb-dc56-4b6d-8b97-b09e4ff31d42\IB. Имя конфигурации УчебныйHTMLСчет85, РежимСовместимостиНеИспользовать, основное приложениеУправляемоеПриложение. Windows8.5.1.1343, толстый управляемый клиент. Путь/имя/версия проверяются точно; иной формат native строки подключения откажет без fuzzy fallback. UUID в имени папки — маркер лаборатории, не UUID ИБ.
Создайте единственную свою роль HTML85Администратор с полными правами только этой пустой CF, включая администрирование для native ПолучитьПользователей. Создайте единственного собственного пользователя HTML85Ученик и назначьте роль. Код берет настоящий ТекущийПользователь и проверяет UUID Users[0] только после Count1; никаких placeholders UUID пользователя и операций создания/записи пользователя нет. Не используйте рабочую УТ/КА/УНФ/БП, не подключайте расширения. Эти действия здесь не выполнялись.
Конфигурация→Языки: оставьте ровно один язык Русский с кодом ru; ОсновнойЯзыкРусский. Общие→ОбщиеМакеты→Добавить НакладнаяHTML85 типаHTMLДокумент. В штатном редакторе HTML вручную вставьте весь visible supporting module НакладнаяHTML85 как одну строку без дополнительных переводов строк или editor-generated разметки. Это исходник собственного compiled макета, не URL/файл для сетевого чтения. GetText требует точное совпадение с этим образцом, не исправляет чужой или переформатированный HTML.
Общие→ОбщиеМодули→СчетHTMLПамять85. СерверДа, Клиент(управляемое приложение)Нет, Клиент(обычное приложение)Нет, ГлобальныйНет, ВызовСервераНет, ПривилегированныйНет. Вставьте целиком CODE. Серверная процедура формы вызывает модуль в своем server context. Shell.КодЯзыкаМакета доступно только сервер/внешнее соединение: его не читает и не устанавливает клиент.
Общие→ОбщиеФормы→ПроверкаСчетаHTML85, управляемая форма без основного реквизита. Реквизиты Количество85/Сумма85 — Число12,0; Статус85Строка20; Протокол85Строка неограниченной длины; Остановка85/Завершено85Булево, начальные False. Первые4 разместите как readonly поля, без HTML-поля/браузера; два флага не показывайте пользователю. Единственная команда Проверить85, ДействиеПроверить85(Команда), кнопка с КомандаПроверить85. В модуль формы вставьте FORM целиком.
Конфигурация→Открыть модуль управляемого приложения: APPLICATION целиком. Реальное ПриНачалеРаботыСистемы() без параметров открывает только own common form, UniqueTrue не ищет прежнюю форму. Событие вручную не вызывается. Ни один HTML DOM объект не передается клиенту: только количество, сумма, полный текстовый снимок и статус после native server readback.
После будущей ручной проверки синтаксиса, сохранения CF и обновления именно своей учебной ИБ запустите толстый управляемый клиент и нажмите Проверить85 один раз. Ожидаемый протокол: BOOK|3|250|750;TEA|2|150|300;, количество5, сумма1050, статусVERIFIED. Второй клик отвергается после успеха; после ошибки локальный и серверный sticky flags запрещают повтор и слепую очистку.
Пример не вызывает CreateTextNode/CreateComment и не маскирует TextDOM под TextHTML. Value setter своего нового Attribute создает текстового ребенка; настоящий ChildNodes.Item возвращает union с TextHTML. Перед каждым native перемещением exact type, Count и own OwnerDocument подтверждаются. Если реализация выдала другой тип/неожиданное число детей, работа останавливается: runtime принадлежность не выдается за измеренную здесь.
Для собственного status siblingPrev/siblingNext проверяются до изменений и после каждого шага. Ожидаем Undefined на этом подготовленном атрибуте; другое состояние вызывает отказ, а не обход строк по sibling атрибута. Это проверка конкретной границы own attribute, не универсальная гарантия реализации. Text.ParentNode вообще не применяется для доказательства типа родителя: native declared return неоднозначен. Членство доказывается own Attr.ChildNodes.Item identity.
Отдельные будущие ручные отрицательные подготовки выполняйте только в НОВОМ собственном сеансе: лишняя третья строка, измененная цена/сумма, другой шаблон, незнакомый 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>Разбор по шагам
Native GetCommonTemplate1 возвращает union: сначала реальный TypeShell guard. Original GetText0 сверяется с видимым HTML. CodeLanguage baseline допускает только Undefined/ru; свой ru задается только на сервере и читается обратно.
Native Shell.GetHTMLDocument0 дает настоящий ДокументHTML; DocumentElement→actualChildNodes обход с ограничениями глубины/количества находит свой DIV и таблицу, без guessed GetElementById/списка DOM alias или жесткого индекса TBODY.
Native Table.GetRows0 и Row.Cells читаются полностью: ровно2строки x4ячейки, все товары/qty/price/amount; число5/1050 вычисляется из actual прочитанного текста, а не возвращается из prepared golden вместо reader.
Свой status проверяется по имени, OwnerDocument, OwnerElement и actual GetAttributeNode identity. Оба readonly sibling используются как guard границы статуса; строки берутся только настоящей коллекцией таблицы.
Три новые собственные Attribute buffers держат CHECK, ED, VERIFI. Value setter создает текст, настоящий ChildNodes.Item0 с TypeTextHTML/OwnerDoc/identity проверяется до native перемещений. Никакого NewAttribute/NewHTMLText/CreateTextNode или подмены return aliases.
Remove1 возвращает прежний DRAFT; Append1 переносит ED; Insert2 ставит CHECK передED; Replace2 возвращает старый CHECK и переноситVERIFI; Normalize0 оставляет VERIFIED и объединяет2→1actual child. После каждого шага источник и полный native numeric snapshot перечитываются.
Язык восстанавливается только после полного verified success и guard текущего ru, именно к прочитанному baseline. GetText снова проверяет ORIGINAL source; возвращаемый final status читается с живого Attribute.Value, не из GetText и не из константы результата.
Как проверить результат
Будущий manual native result: BOOK3×250=750; TEA2×150=300; qty5/total1050 до, на всех5шагах и после. Полный snapshot восьми ячеек одинаков.
Actual status child counts1→0→1→2→2→1; значенияDRAFT→empty→ED→CHECKED→VERIFIED→VERIFIED. Возвращенные узлы проверяются по identity, исходные buffer children после перемещения0.
Исходный compiled GetText точный и неизменный; живой statusVERIFIED проверяется отдельно. Нет обещания GetText serialization/HTML browser pixels/нормализации всего документа.
Здесь native static signatures/context/readonly/factory scope и negative mutants; runtimeVerifiedFalse, реальная1С/CF/GUI/IB/network0.
Ожидаемый результат
Ожидаемый будущий ручной результат: две прежние строки, количество5, сумма1050 и живой native statusVERIFIED из одного текстового сегмента. Исходный HTML отдельно остается исходным, language baseline восстановлен после success. Этот runtime результат здесь не выполнялся.
На что обратить внимание
Оболочка, АтрибутHTML и КомментарийHTML не имеют прямого ctor. ДокументHTML ctor имеет required title и не является parser HTML string; здесь он не используется.
СоздатьТекстовыйУзел/СоздатьКомментарий объявляют DOM returns. Этот урок получает actualTextHTML только через documented native child list и требует его runtime type. Не превращайте literal alias/переменную в proof типа.
TextHTML в установленной справке помечен не рекомендуемым с8.2: это точный ограниченный урок поддержки существующего HTML-макета. Не переносите его без проверки в современный браузерный DOM/API.
Общий native CompareDocumentPosition не документирует result; COM getters и legacy Comment child/Text operations не кредитуются. Comment.Normalize leaf no-op не добавлен ради числа.
Value setter уничтожает прежних детей только своего нового буфера. Дочерние методы перемещают реальные узлы, могут отказать при wrong owner/readonly/invalid child; partial mutation не атомарна. После исключения нет продолжения, automatic rollback/retry.
Свойство язык выбирает локализацию для getter; typed readback ru не доказывает renderer/visual language. GetText остается исходным текстом, не export измененной DOM. Никаких DBwrites, печати, сети, COM или исполнения внешнего HTML.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.