Различить тот же HTML-документ и равную глубокую копию

Учебные задачи

Одна переменная ссылается на исходный документ, другая — на его глубокую копию. Проверяем идентичность и структурное равенство, затем меняем текст только в копии.

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

Полный серверный общий модуль УчебныйДокументHTML85. Свой HTML создаётся строкой и разбирается в памяти, без браузера и внешних источников.

Подготовка

  1. Используйте отдельную учебную базу 8.5.1.1343. Создайте общий модуль УчебныйДокументHTML85: Сервер — Да, Клиент — Нет, Глобальный — Нет, Вызов сервера — Нет, Привилегированный — Нет.

  2. Вставьте весь приведённый модуль одного урока. В своей управляемой учебной обработке создайте команду и клиентский обработчик, вызывающий свою процедуру с директивой &НаСервереБезКонтекста. В её тело вставьте УчебныйДокументHTML85.ВыполнитьПример();.

  3. Источник HTML полностью записан в коде: свой вымышленный заказ, покупатель, книга, ручка и элементы с явно заданными id. ЧтениеHTML и ПостроительDOM получают строку, а не URL или внешний файл.

  4. Разбор HTML в этом уроке не открывает браузер, не отправляет форму, не загружает картинки и не исполняет JavaScript. Файлы, сеть, печать, рабочие документы и регистры не используются.

  5. Каждый запуск создаёт новый собственный документ в памяти. Поставьте точку останова перед конечными Сообщить и исследуйте Документ, его ЭлементДокумента и указанные переменные урока в серверном отладчике.

  6. ДокументHTML — корневой объект дерева, а его ЭлементДокумента, Тело и отдельный блок — другие узлы. Одинаковые имена методов не означают одинаковые правила допустимых дочерних узлов.

  7. Результаты ниже ожидаемые. В 1С код не запускался; статическая сверка сигнатур и readonly не подтверждает все особенности реализации HTML DOM вашей среды. Выполните проверки только на своём учебном стенде.

Процедура ВыполнитьПример() Экспорт
    HTML = "<html><head><title>Учебный заказ</title><meta id='meta' name='description' content='Вымышленный заказ'></head>
    |<body id='body'><p id='note'>Заказ существует только в памяти</p><pre id='code'>A-01: 3
    |B-02: 1</pre>
    |<form id='order' name='order' action='' method='get'>
    |<input id='customer' name='customer' type='text' value='Учебный покупатель'>
    |<input id='accepted' name='accepted' type='checkbox' value='yes'>
    |<button id='preview' name='preview' type='button' value='preview'>Предпросмотр</button></form>
    |<table id='items' summary='Книга и ручка'><caption id='caption'>Товары</caption><colgroup><col id='column'></colgroup><tbody>
    |<tr id='book'><td id='book-name'>Книга</td><td>3</td></tr><tr id='pen'><td>Ручка</td><td>1</td></tr>
    |</tbody></table><a id='help' name='help' href='#note'>Пояснение</a><img id='logo' alt='Учебная картинка без источника'>
    |</body></html>";
    Чтение = Новый ЧтениеHTML;
    Чтение.УстановитьСтроку(HTML);
    Попытка
        Построитель = Новый ПостроительDOM;
        Документ = Построитель.Прочитать(Чтение);
    Исключение
        Чтение.Закрыть();
        ВызватьИсключение;
    КонецПопытки;
    Чтение.Закрыть();
    Если ТипЗнч(Документ) <> Тип("ДокументHTML") Тогда
        ВызватьИсключение "Ожидался ДокументHTML, а не XML-документ";
    КонецЕсли;
    Документ.Нормализовать();
    ТаЖеСсылка = Документ;
    Копия = Документ.КлонироватьУзел(Истина);
    Если ТипЗнч(Копия) <> Тип("ДокументHTML") Тогда
        ВызватьИсключение "Ожидалась глубокая копия HTML-документа";
    КонецЕсли;
    Копия.Нормализовать();
    Сообщить(Документ.УзелИдентичен(ТаЖеСсылка));
    Сообщить(Не Документ.УзелИдентичен(Копия));
    Сообщить(Документ.УзелРавен(Копия));
    Сообщить(Документ.УзелРавен(Документ));
    ИсходноеПояснение = Документ.ПолучитьЭлементПоИдентификатору("note");
    ПояснениеКопии = Копия.ПолучитьЭлементПоИдентификатору("note");
    Если ИсходноеПояснение = Неопределено Или ПояснениеКопии = Неопределено Тогда
        ВызватьИсключение "В обеих собственных версиях нужно пояснение note";
    КонецЕсли;
    ИсходныйТекст = ИсходноеПояснение.ТекстовоеСодержимое;
    ПояснениеКопии.ТекстовоеСодержимое = "Изменена только учебная копия";
    Сообщить(ИсходноеПояснение.ТекстовоеСодержимое = ИсходныйТекст);
    Сообщить(Не Документ.УзелРавен(Копия));

КонецПроцедуры

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

  1. Создать свой исходный документ из строки и нормализовать его перед сравнением.

  2. Присваивание ТаЖеСсылка=Документ не копирует дерево. УзелИдентичен проверяет ссылку на тот же объект, а не сходство его текста.

  3. КлонироватьУзел(Истина) создаёт глубокую копию. Проверяем её тип перед использованием свойств документа.

  4. Нормализовать обе версии: по справке нормализация влияет на структурное равенство узлов.

  5. Исходный документ идентичен ТаЖеСсылка, не идентичен копии, но равен ей по структуре. Самому себе он также равен.

  6. Найти собственное пояснение note в каждой версии и проверить оба результата на Неопределено. Менять ТекстовоеСодержимое только найденного узла копии.

  7. Сохранность исходного текста показывает независимость глубокого дерева. После изменения копия уже структурно не равна оригиналу.

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

  1. Шесть конечных сравнений должны дать Истина: четыре до правки и два после неё.

  2. В отладчике оригинальное note сохраняет текст Заказ существует только в памяти, копия содержит новое пояснение.

  3. УзелИдентичен и УзелРавен отвечают на разные вопросы. Не используйте равенство текста как доказательство общего объекта.

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

Различие ссылочной идентичности и структурного равенства показано на полноценном собственном документе и его изменённой копии.

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

  1. УзелРавен не сравнивает пользовательские данные и не учитывает ряд служебных ссылок документа-владельца и родителей.

  2. Слово Истина в КлонироватьУзел относится к глубине копирования, не к записи документа в базу.

  3. Нельзя применять этот код к неизвестной странице пользователя: оба документа созданы в этом уроке.

  4. Никакой файл или окно браузера не изменяется; запуска в 1С не было.

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

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

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

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

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