Отбор атрибутов не добавляет их к обходу дочерних тегов: для этого урок задаёт сам атрибут корнем отдельного итератора.
Где и как запускать
Полный серверный общий модуль собственной учебной базы; работа с собственными DOM в памяти.
Подготовка
Собственная учебная база 8.5.1.1343. Создайте серверный общий модуль УчебныйОбходXML с флагом Сервер. Вставьте полный модуль одного урока и вызовите УчебныйОбходXML.ВыполнитьПример() из серверной команды собственной обработки.
Деревья создаются из фиксированных учебных данных. Нет чтения файлов, запросов сети, записей базы или произвольного внешнего XML.
Свойства ФильтрУзловDOM доступны только для чтения. Набор видов узлов задаётся параметрами конструктора, а не присваиванием ОтображатьЭлемент=Истина.
Параметры конструктора — значения перечисления ПараметрыОтбораУзловDOM, не Булево. Пустые позиции в коде оставляют соответствующие виды не включёнными согласно справке.
Подсчёт относится к дереву без форматирующих пробелов, построенному этим уроком. Запуск внутри 1С здесь ещё не подтверждён.
Процедура ВыполнитьПример() Экспорт
Документ = Новый ДокументDOM("", "products");
Корень = Документ.ЭлементДокумента;
Корень.УстановитьАтрибут("code", "A-01");
Атрибут = Корень.ПолучитьУзелАтрибута("code");
ФильтрАтрибута = Новый ФильтрУзловDOM(, , ПараметрыОтбораУзловDOM.ОтображатьАтрибут);
Сообщить(ФильтрАтрибута.ОтображатьАтрибут);
Атрибуты = СобратьУчебныеУзлы(Документ, Атрибут, ФильтрАтрибута);
Сообщить(Атрибуты.Количество() = 1);
Сообщить(Атрибуты[0] = Атрибут);
Сообщить(Атрибуты[0].Значение = "A-01");
Фрагмент = Документ.СоздатьФрагментДокумента();
Фрагмент.ДобавитьДочерний(Документ.СоздатьЭлемент("book"));
Фрагмент.ДобавитьДочерний(Документ.СоздатьЭлемент("pen"));
ФильтрФрагмента = Новый ФильтрУзловDOM(, ПараметрыОтбораУзловDOM.ОтображатьЭлемент, , , , , , , , , , ПараметрыОтбораУзловDOM.ОтображатьФрагментДокумента);
Сообщить(ФильтрФрагмента.ОтображатьФрагментДокумента);
Сообщить(ФильтрФрагмента.ОтображатьЭлемент);
Узлы = СобратьУчебныеУзлы(Документ, Фрагмент, ФильтрФрагмента);
Сообщить(Узлы.Количество() = 3);
Сообщить(Узлы[0] = Фрагмент);
Сообщить(Узлы[1].ИмяУзла = "book");
Сообщить(Узлы[2].ИмяУзла = "pen");
Сообщить(Корень.ДочерниеУзлы.Количество() = 0);
КонецПроцедуры
Функция СобратьУчебныеУзлы(Документ, Корень, Фильтр)
Результат = Новый Массив;
Итератор = Документ.СоздатьИтераторУзлов(Корень, Фильтр, Ложь);
ОшибкаОбхода = "";
Попытка
Узел = Итератор.СледующийУзел();
Пока Узел <> Неопределено Цикл
Результат.Добавить(Узел);
Узел = Итератор.СледующийУзел();
КонецЦикла;
Исключение
ОшибкаОбхода = ОписаниеОшибки();
КонецПопытки;
ОшибкаЗавершения = "";
Попытка
Итератор.Отсоединить();
Исключение
ОшибкаЗавершения = ОписаниеОшибки();
КонецПопытки;
Если Не ПустаяСтрока(ОшибкаОбхода) Или Не ПустаяСтрока(ОшибкаЗавершения) Тогда
ВызватьИсключение ОшибкаОбхода + " " + ОшибкаЗавершения;
КонецЕсли;
Возврат Результат;
КонецФункцииРазбор по шагам
Атрибут code принадлежит products, но не содержится в его ДочерниеУзлы. Передаём реальный АтрибутDOM как самостоятельный корень.
Фильтр атрибута оставляет в результате один атрибут. Его значение A-01 читаем после проверки количества.
Отдельный ФрагментДокументаDOM принадлежит тому же документу и содержит book/pen. Фрагмент ещё не вставлен в products.
Второй фильтр включает фрагмент и элементы, поэтому возвращаются сам фрагмент и два его ребёнка.
Последнее сравнение доказывает, что обход не переместил фрагмент в корень документа.
Как проверить результат
Одиннадцать проверок ожидаются Истина: четыре для атрибута и семь для фрагмента/неизменности корня.
Фрагмент остаётся отдельным контейнером; в products нет новых дочерних тегов.
Ожидаемый результат
Показано применение двух специальных видов отбора с настоящими корнями, а не ожиданием атрибутов среди детей.
На что обратить внимание
Добавление фрагмента в другой узел перемещает его детей, поэтому это другая операция и другой результат.
Не путать значение АтрибутDOM со значением ФильтрУзловDOM: типы создаются разными API.
Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.