Читайте дальше...
Создание и заполнение дерева значений
// Создание дерева значений, добавление корневых и дочерних элементов
Процедура СозданиеДереваЗначений()
// Создаем новое дерево значений
Дерево = Новый ДеревоЗначений;
// Добавляем колонки
Дерево.Колонки.Добавить("Наименование");
Дерево.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
Дерево.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
// Добавляем корневые элементы (уровень 0)
Строка1 = Дерево.Строки.Добавить();
Строка1.Наименование = "Электроника";
Строка1.Количество = 0;
Строка1.Сумма = 0;
// Добавляем дочерние элементы к первой строке
Дочерняя1 = Строка1.Строки.Добавить();
Дочерняя1.Наименование = "Ноутбуки";
Дочерняя1.Количество = 10;
Дочерняя1.Сумма = 500000;
Дочерняя2 = Строка1.Строки.Добавить();
Дочерняя2.Наименование = "Мониторы";
Дочерняя2.Количество = 5;
Дочерняя2.Сумма = 75000;
// Добавляем второй корневой элемент
Строка2 = Дерево.Строки.Добавить();
Строка2.Наименование = "Мебель";
Строка2.Количество = 0;
Строка2.Сумма = 0;
Дочерняя3 = Строка2.Строки.Добавить();
Дочерняя3.Наименование = "Столы";
Дочерняя3.Количество = 8;
Дочерняя3.Сумма = 80000;
Дочерняя4 = Строка2.Строки.Добавить();
Дочерняя4.Наименование = "Стулья";
Дочерняя4.Количество = 20;
Дочерняя4.Сумма = 60000;
// Вывод дерева
Сообщить("Структура дерева:");
ВывестиДерево(Дерево, "");
КонецПроцедуры
Процедура ВывестиДерево(Дерево, Отступ)
Для Каждого Строка Из Дерево.Строки Цикл
Сообщить(Отступ + Строка.Наименование + " (кол-во: " + Строка.Количество +
", сумма: " + Строка.Сумма + ")");
Если Строка.Строки.Количество() > 0 Тогда
ВывестиПоддерево(Строка.Строки, Отступ + " ");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ВывестиПоддерево(Строки, Отступ)
Для Каждого Строка Из Строки Цикл
Сообщить(Отступ + Строка.Наименование + " (кол-во: " + Строка.Количество +
", сумма: " + Строка.Сумма + ")");
Если Строка.Строки.Количество() > 0 Тогда
ВывестиПоддерево(Строка.Строки, Отступ + " ");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Обход дерева значений (рекурсивный и итеративный)
// Различные способы обхода дерева значений
Процедура ОбходДерева()
// Создаем тестовое дерево
Дерево = СоздатьТестовоеДерево();
// Способ 1: рекурсивный обход
Сообщить("Рекурсивный обход:");
РекурсивныйОбход(Дерево.Строки, "");
// Способ 2: обход с использованием стека (без рекурсии)
Сообщить("Обход с использованием стека:");
ОбходЧерезСтек(Дерево);
// Способ 3: обход с получением всех строк (плоский список)
Сообщить("Получение всех строк в плоский список:");
ВсеСтроки = ПолучитьВсеСтроки(Дерево);
Для Каждого Строка Из ВсеСтроки Цикл
Сообщить(Строка.Наименование + " (уровень: " + Строка.Уровень() + ")");
КонецЦикла;
КонецПроцедуры
Функция СоздатьТестовоеДерево()
Дерево = Новый ДеревоЗначений;
Дерево.Колонки.Добавить("Наименование");
Дерево.Колонки.Добавить("Код", Новый ОписаниеТипов("Число"));
Корень1 = Дерево.Строки.Добавить();
Корень1.Наименование = "Отдел 1";
Корень1.Код = 1;
Дочер1 = Корень1.Строки.Добавить();
Дочер1.Наименование = "Группа 1.1";
Дочер1.Код = 11;
Внук1 = Дочер1.Строки.Добавить();
Внук1.Наименование = "Сотрудник 1.1.1";
Внук1.Код = 111;
Корень2 = Дерево.Строки.Добавить();
Корень2.Наименование = "Отдел 2";
Корень2.Код = 2;
Дочер2 = Корень2.Строки.Добавить();
Дочер2.Наименование = "Группа 2.1";
Дочер2.Код = 21;
Возврат Дерево;
КонецФункции
Процедура РекурсивныйОбход(Строки, Отступ)
Для Каждого Строка Из Строки Цикл
Сообщить(Отступ + Строка.Наименование + " (код: " + Строка.Код + ")");
РекурсивныйОбход(Строка.Строки, Отступ + " ");
КонецЦикла;
КонецПроцедуры
Процедура ОбходЧерезСтек(Дерево)
Стек = Новый Массив;
// Добавляем все корневые строки в стек в обратном порядке
Для Инд = Дерево.Строки.Количество() - 1 По 0 Шаг -1 Цикл
Стек.Добавить(Дерево.Строки[Инд]);
КонецЦикла;
Пока Стек.Количество() > 0 Цикл
Текущий = Стек[Стек.Количество() - 1];
Стек.Удалить(Стек.Количество() - 1);
Сообщить(Текущий.Наименование + " (код: " + Текущий.Код + ")");
// Добавляем дочерние элементы в стек
Для Инд = Текущий.Строки.Количество() - 1 По 0 Шаг -1 Цикл
Стек.Добавить(Текущий.Строки[Инд]);
КонецЦикла;
КонецЦикла;
КонецПроцедуры
Функция ПолучитьВсеСтроки(Дерево)
Результат = Новый Массив;
Строки = Дерево.Строки;
ДобавитьСтрокиВМассив(Строки, Результат);
Возврат Результат;
КонецФункции
Процедура ДобавитьСтрокиВМассив(Строки, Массив)
Для Каждого Строка Из Строки Цикл
Массив.Добавить(Строка);
Если Строка.Строки.Количество() > 0 Тогда
ДобавитьСтрокиВМассив(Строка.Строки, Массив);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Поиск элементов в дереве значений
// Поиск строк в дереве по различным критериям
Процедура ПоискВДереве()
// Создаем дерево с данными
Дерево = Новый ДеревоЗначений;
Дерево.Колонки.Добавить("Наименование");
Дерево.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число"));
Дерево.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
Категория1 = Дерево.Строки.Добавить();
Категория1.Наименование = "Электроника";
Товар1 = Категория1.Строки.Добавить();
Товар1.Наименование = "Ноутбук"; Товар1.Цена = 50000; Товар1.Количество = 10;
Товар2 = Категория1.Строки.Добавить();
Товар2.Наименование = "Монитор"; Товар2.Цена = 15000; Товар2.Количество = 5;
Категория2 = Дерево.Строки.Добавить();
Категория2.Наименование = "Мебель";
Товар3 = Категория2.Строки.Добавить();
Товар3.Наименование = "Стол"; Товар3.Цена = 8000; Товар3.Количество = 8;
Товар4 = Категория2.Строки.Добавить();
Товар4.Наименование = "Стул"; Товар4.Цена = 2500; Товар4.Количество = 20;
// Поиск по наименованию
НайденнаяСтрока = НайтиПоНаименованию(Дерево, "Монитор");
Если НайденнаяСтрока <> Неопределено Тогда
Сообщить("Найден товар: " + НайденнаяСтрока.Наименование +
", цена: " + НайденнаяСтрока.Цена);
КонецЕсли;
// Поиск всех товаров с ценой > 10000
Результаты = НайтиПоУсловию(Дерево, "Цена > 10000");
Сообщить("Товары с ценой более 10000:");
Для Каждого Строка Из Результаты Цикл
Сообщить(" " + Строка.Наименование + " - " + Строка.Цена);
КонецЦикла;
// Поиск по родителю
Родитель = НайтиРодителя(Дерево, "Стул");
Если Родитель <> Неопределено Тогда
Сообщить("Родитель стула: " + Родитель.Наименование);
КонецЕсли;
КонецПроцедуры
Функция НайтиПоНаименованию(Дерево, Наименование)
Для Каждого Строка Из Дерево.Строки Цикл
Если Строка.Наименование = Наименование Тогда
Возврат Строка;
КонецЕсли;
Результат = НайтиСтрокуВВетке(Строка.Строки, Наименование);
Если Результат <> Неопределено Тогда
Возврат Результат;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Функция НайтиСтрокуВВетке(Строки, Наименование)
Для Каждого Строка Из Строки Цикл
Если Строка.Наименование = Наименование Тогда
Возврат Строка;
КонецЕсли;
Результат = НайтиСтрокуВВетке(Строка.Строки, Наименование);
Если Результат <> Неопределено Тогда
Возврат Результат;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Функция НайтиПоУсловию(Дерево, УсловиеВыражение)
Результат = Новый Массив;
ДобавитьПодходящиеСтроки(Дерево.Строки, УсловиеВыражение, Результат);
Возврат Результат;
КонецФункции
Процедура ДобавитьПодходящиеСтроки(Строки, УсловиеВыражение, Результат)
Для Каждого Строка Из Строки Цикл
// Упрощенная проверка (в реальном коде используйте Вычислить)
Если Строка.Цена > 10000 Тогда
Результат.Добавить(Строка);
КонецЕсли;
Если Строка.Строки.Количество() > 0 Тогда
ДобавитьПодходящиеСтроки(Строка.Строки, УсловиеВыражение, Результат);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Функция НайтиРодителя(Дерево, ИмяРебенка)
Для Каждого Строка Из Дерево.Строки Цикл
Родитель = НайтиРодителяВВетке(Строка, ИмяРебенка);
Если Родитель <> Неопределено Тогда
Возврат Родитель;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Функция НайтиРодителяВВетке(ПотенциальныйРодитель, ИмяРебенка)
Для Каждого Ребенок Из ПотенциальныйРодитель.Строки Цикл
Если Ребенок.Наименование = ИмяРебенка Тогда
Возврат ПотенциальныйРодитель;
КонецЕсли;
Результат = НайтиРодителяВВетке(Ребенок, ИмяРебенка);
Если Результат <> Неопределено Тогда
Возврат Результат;
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Агрегация и подсчет итогов в дереве значений
// Расчет итоговых сумм и количества на уровнях дерева
Процедура ПодсчетИтоговВДереве()
Дерево = Новый ДеревоЗначений;
Дерево.Колонки.Добавить("Наименование");
Дерево.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
Дерево.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));
Дерево.Колонки.Добавить("ИтогКоличество", Новый ОписаниеТипов("Число"));
Дерево.Колонки.Добавить("ИтогСумма", Новый ОписаниеТипов("Число"));
// Заполняем дерево
Филиал1 = Дерево.Строки.Добавить();
Филиал1.Наименование = "Филиал Северный";
Отдел1 = Филиал1.Строки.Добавить();
Отдел1.Наименование = "Отдел продаж";
Отдел1.Количество = 5;
Отдел1.Сумма = 500000;
Отдел2 = Филиал1.Строки.Добавить();
Отдел2.Наименование = "Отдел закупок";
Отдел2.Количество = 3;
Отдел2.Сумма = 300000;
Филиал2 = Дерево.Строки.Добавить();
Филиал2.Наименование = "Филиал Южный";
Отдел3 = Филиал2.Строки.Добавить();
Отдел3.Наименование = "Отдел продаж";
Отдел3.Количество = 8;
Отдел3.Сумма = 800000;
// Рассчитываем итоги
РассчитатьИтогиДерева(Дерево);
// Выводим дерево с итогами
Сообщить("Дерево с рассчитанными итогами:");
ВывестиДеревоСИтогами(Дерево.Строки, "");
КонецПроцедуры
Функция РассчитатьИтогиДерева(Дерево)
РассчитатьИтогиВетки(Дерево.Строки);
КонецФункции
Функция РассчитатьИтогиВетки(Строки)
Для Каждого Строка Из Строки Цикл
Если Строка.Строки.Количество() > 0 Тогда
// Рекурсивно рассчитываем итоги детей
РассчитатьИтогиВетки(Строка.Строки);
// Суммируем данные детей
ИтогКол = 0;
ИтогСум = 0;
Для Каждого Ребенок Из Строка.Строки Цикл
Если Ребенок.Строки.Количество() > 0 Тогда
ИтогКол = ИтогКол + Ребенок.ИтогКоличество;
ИтогСум = ИтогСум + Ребенок.ИтогСумма;
Иначе
ИтогКол = ИтогКол + Ребенок.Количество;
ИтогСум = ИтогСум + Ребенок.Сумма;
КонецЕсли;
КонецЦикла;
Строка.ИтогКоличество = ИтогКол;
Строка.ИтогСумма = ИтогСум;
Иначе
// Для листовых узлов итог равен собственным значениям
Строка.ИтогКоличество = Строка.Количество;
Строка.ИтогСумма = Строка.Сумма;
КонецЕсли;
КонецЦикла;
КонецФункции
Процедура ВывестиДеревоСИтогами(Строки, Отступ)
Для Каждого Строка Из Строки Цикл
Сообщить(Отступ + Строка.Наименование +
" (собственные: кол-во=" + Строка.Количество +
", сумма=" + Строка.Сумма +
" | итого: кол-во=" + Строка.ИтогКоличество +
", сумма=" + Строка.ИтогСумма + ")");
Если Строка.Строки.Количество() > 0 Тогда
ВывестиДеревоСИтогами(Строка.Строки, Отступ + " ");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Загрузка данных в дерево из таблицы значений
// Преобразование плоской таблицы в иерархическое дерево
Процедура ТаблицаВДерево()
// Исходная плоская таблица
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Код");
Таблица.Колонки.Добавить("Родитель");
Таблица.Колонки.Добавить("Наименование");
Таблица.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
Таблица.Добавить().Код = 1; Таблица[0].Родитель = 0; Таблица[0].Наименование = "Все товары"; Таблица[0].Количество = 0;
Таблица.Добавить().Код = 2; Таблица[1].Родитель = 1; Таблица[1].Наименование = "Электроника"; Таблица[1].Количество = 0;
Таблица.Добавить().Код = 3; Таблица[2].Родитель = 2; Таблица[2].Наименование = "Ноутбуки"; Таблица[2].Количество = 15;
Таблица.Добавить().Код = 4; Таблица[3].Родитель = 2; Таблица[3].Наименование = "Мониторы"; Таблица[3].Количество = 8;
Таблица.Добавить().Код = 5; Таблица[4].Родитель = 1; Таблица[4].Наименование = "Мебель"; Таблица[4].Количество = 0;
Таблица.Добавить().Код = 6; Таблица[5].Родитель = 5; Таблица[5].Наименование = "Столы"; Таблица[5].Количество = 10;
Таблица.Добавить().Код = 7; Таблица[6].Родитель = 5; Таблица[6].Наименование = "Стулья"; Таблица[6].Количество = 25;
// Создаем дерево
Дерево = Новый ДеревоЗначений;
Дерево.Колонки.Добавить("Код", Новый ОписаниеТипов("Число"));
Дерево.Колонки.Добавить("Наименование");
Дерево.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
// Создаем соответствие для быстрого поиска строк по коду
ТаблицаКодировка = Новый Соответствие;
Для Каждого СтрокаТаблицы Из Таблица Цикл
ТаблицаКодировка.Вставить(СтрокаТаблицы.Код, СтрокаТаблицы);
КонецЦикла;
// Функция добавления строки в дерево по родителю
Процедура ДобавитьСтрокуВДерево(РодительСтрока, СтрокаДанных, Дерево)
НоваяСтрока = РодительСтрока.Строки.Добавить();
НоваяСтрока.Код = СтрокаДанных.Код;
НоваяСтрока.Наименование = СтрокаДанных.Наименование;
НоваяСтрока.Количество = СтрокаДанных.Количество;
КонецПроцедуры
// Находим корневые элементы и строим дерево
Для Каждого СтрокаТаблицы Из Таблица Цикл
Если СтрокаТаблицы.Родитель = 0 Тогда
// Корневой элемент
Корень = Дерево.Строки.Добавить();
Корень.Код = СтрокаТаблицы.Код;
Корень.Наименование = СтрокаТаблицы.Наименование;
Корень.Количество = СтрокаТаблицы.Количество;
КонецЕсли;
КонецЦикла;
// Рекурсивное добавление дочерних элементов
Для Каждого Корень Из Дерево.Строки Цикл
ДобавитьДочерниеЭлементы(Корень, ТаблицаКодировка);
КонецЦикла;
// Вывод результата
Сообщить("Дерево, построенное из таблицы:");
ВывестиДеревоПоСтрокам(Дерево.Строки, "");
КонецПроцедуры
Процедура ДобавитьДочерниеЭлементы(Родитель, ТаблицаКодировка)
Для Каждого КлючЗначение Из ТаблицаКодировка Цикл
СтрокаДанных = КлючЗначение.Значение;
Если СтрокаДанных.Родитель = Родитель.Код Тогда
// Создаем дочерний элемент
Ребенок = Родитель.Строки.Добавить();
Ребенок.Код = СтрокаДанных.Код;
Ребенок.Наименование = СтрокаДанных.Наименование;
Ребенок.Количество = СтрокаДанных.Количество;
// Рекурсивно добавляем внуков
ДобавитьДочерниеЭлементы(Ребенок, ТаблицаКодировка);
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Процедура ВывестиДеревоПоСтрокам(Строки, Отступ)
Для Каждого Строка Из Строки Цикл
Сообщить(Отступ + Строка.Наименование + " (код: " + Строка.Код +
", кол-во: " + Строка.Количество + ")");
Если Строка.Строки.Количество() > 0 Тогда
ВывестиДеревоПоСтрокам(Строка.Строки, Отступ + " ");
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Сохранение и загрузка дерева значений
// Сохранение дерева в XML и восстановление
Процедура СохранениеИЗагрузкаДерева()
// Создаем исходное дерево
Исходное = Новый ДеревоЗначений;
Исходное.Колонки.Добавить("Имя");
Исходное.Колонки.Добавить("Возраст", Новый ОписаниеТипов("Число"));
Корень = Исходное.Строки.Добавить();
Корень.Имя = "Группа 1";
Корень.Возраст = 0;
Ребенок1 = Корень.Строки.Добавить();
Ребенок1.Имя = "Иванов";
Ребенок1.Возраст = 25;
Ребенок2 = Корень.Строки.Добавить();
Ребенок2.Имя = "Петров";
Ребенок2.Возраст = 30;
// Сохраняем в XML
СтрокаXML = СохранитьДеревоВXML(Исходное);
Сообщить("Сериализованное дерево:");
Сообщить(Лев(СтрокаXML, 500) + "...");
// Восстанавливаем из XML
Восстановленное = ЗагрузитьДеревоXML(СтрокаXML);
// Сравниваем
Сообщить("Восстановленное дерево:");
ВывестиДерево(Восстановленное, "");
// Сравниваем идентичность
Совпадают = СравнитьДеревья(Исходное, Восстановленное);
Сообщить("Деревья совпадают: " + ?(Совпадают, "Да", "Нет"));
КонецПроцедуры
Функция СохранитьДеревоВXML(Дерево)
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("ДеревоЗначений");
// Сохраняем структуру колонок
ЗаписьXML.ЗаписатьНачалоЭлемента("Колонки");
Для Каждого Колонка Из Дерево.Колонки Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("Колонка");
ЗаписьXML.ЗаписатьАтрибут("Имя", Колонка.Имя);
ЗаписьXML.ЗаписатьАтрибут("Тип", Строка(Колонка.ТипЗначения));
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
// Сохраняем строки
ЗаписьXML.ЗаписатьНачалоЭлемента("Строки");
СохранитьВеткуВXML(Дерево.Строки, ЗаписьXML);
ЗаписьXML.ЗаписатьКонецЭлемента();
ЗаписьXML.ЗаписатьКонецЭлемента();
Возврат ЗаписьXML.Закрыть();
КонецФункции
Процедура СохранитьВеткуВXML(Строки, ЗаписьXML)
Для Каждого Строка Из Строки Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("Строка");
// Сохраняем значения колонок
ЗаписьXML.ЗаписатьНачалоЭлемента("Значения");
Для Каждого Колонка Из Строки.Владелец().Колонки Цикл
ЗаписьXML.ЗаписатьНачалоЭлемента("Значение");
ЗаписьXML.ЗаписатьАтрибут("Колонка", Колонка.Имя);
ЗаписьXML.ЗаписатьТекст(Строка[Колонка.Имя]);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
// Сохраняем дочерние строки
Если Строка.Строки.Количество() > 0 Тогда
ЗаписьXML.ЗаписатьНачалоЭлемента("Дочерние");
СохранитьВеткуВXML(Строка.Строки, ЗаписьXML);
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЕсли;
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецЦикла;
КонецПроцедуры
Функция ЗагрузитьДеревоXML(СтрокаXML)
ЧтениеXML = Новый ЧтениеXML;
ЧтениеXML.УстановитьСтроку(СтрокаXML);
Дерево = Новый ДеревоЗначений;
// Пропускаем объявление и корневой элемент
ЧтениеXML.Прочитать();
ЧтениеXML.Прочитать();
// Читаем колонки
ЧтениеXML.Прочитать();
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Колонки" Тогда
ЧтениеXML.Прочитать();
Пока ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Колонка" Цикл
Имя = ЧтениеXML.ПолучитьАтрибут("Имя");
ТипСтрока = ЧтениеXML.ПолучитьАтрибут("Тип");
Дерево.Колонки.Добавить(Имя);
ЧтениеXML.Прочитать();
ЧтениеXML.Прочитать();
КонецЦикла;
КонецЕсли;
// Читаем строки
ЧтениеXML.Прочитать();
Если ЧтениеXML.Имя = "Строки" Тогда
ЧтениеXML.Прочитать();
ЗагрузитьВеткуИзXML(Дерево.Строки, ЧтениеXML);
КонецЕсли;
Возврат Дерево;
КонецФункции
Процедура ЗагрузитьВеткуИзXML(СтрокиРодителя, ЧтениеXML)
Пока ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Строка" Цикл
НоваяСтрока = СтрокиРодителя.Добавить();
// Читаем значения колонок
ЧтениеXML.Прочитать();
Если ЧтениеXML.Имя = "Значения" Тогда
ЧтениеXML.Прочитать();
Пока ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЧтениеXML.Имя = "Значение" Цикл
ИмяКолонки = ЧтениеXML.ПолучитьАтрибут("Колонка");
ЧтениеXML.Прочитать();
Значение = ЧтениеXML.Значение;
НоваяСтрока[ИмяКолонки] = Значение;
ЧтениеXML.Прочитать();
ЧтениеXML.Прочитать();
КонецЦикла;
КонецЕсли;
// Читаем дочерние строки
ЧтениеXML.Прочитать();
Если ЧтениеXML.Имя = "Дочерние" Тогда
ЧтениеXML.Прочитать();
ЗагрузитьВеткуИзXML(НоваяСтрока.Строки, ЧтениеXML);
ЧтениеXML.Прочитать();
КонецЕсли;
ЧтениеXML.Прочитать();
КонецЦикла;
КонецПроцедуры
Функция СравнитьДеревья(Дерево1, Дерево2)
Если Дерево1.Колонки.Количество() <> Дерево2.Колонки.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Если Дерево1.Строки.Количество() <> Дерево2.Строки.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Для Инд = 0 По Дерево1.Строки.Количество() - 1 Цикл
Если Не СравнитьВетки(Дерево1.Строки[Инд], Дерево2.Строки[Инд]) Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Функция СравнитьВетки(Строка1, Строка2)
Для Каждого Колонка Из Строка1.Владелец().Колонки Цикл
Если Строка1[Колонка.Имя] <> Строка2[Колонка.Имя] Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Если Строка1.Строки.Количество() <> Строка2.Строки.Количество() Тогда
Возврат Ложь;
КонецЕсли;
Для Инд = 0 По Строка1.Строки.Количество() - 1 Цикл
Если Не СравнитьВетки(Строка1.Строки[Инд], Строка2.Строки[Инд]) Тогда
Возврат Ложь;
КонецЕсли;
КонецЦикла;
Возврат Истина;
КонецФункции
Примечания
// Важные особенности работы с деревом значений:
// 1. Дерево значений предназначено для хранения иерархических данных
// 2. Каждая строка дерева имеет коллекцию Строки для доступа к дочерним элементам
// 3. Уровень вложенности строки можно получить методом Уровень()
// 4. Для обхода дерева используйте рекурсивные функции или стек
// 5. При удалении строки все ее дочерние элементы также удаляются
// 6. Дерево значений часто используется для представления отчетов с группировками
// 7. Для расчета итогов используйте рекурсивное суммирование по дочерним элементам
// 8. Поиск в дереве требует полного обхода, так как нет индексов
// 9. Дерево можно сериализовать в XML для сохранения и передачи
// 10. При загрузке из плоской таблицы нужно строить иерархию по полю-родителю
// 11. Для отображения дерева на форме используйте элемент управления "ДеревоЗначений"
// 12. Производительность дерева снижается при большом количестве вложенных уровней и строк








