Данная публикация развивает тему, поднятую в
https://forum.infostart.ru/forum104/topic194804/
Однако, преобразует не в одноуровневую, а в многоуровневую структуру.
Собственно сам код:
Передаём данные файла:
Функция ПрочитатьФайлНаСервере(ДанныеФайла,СвернутьПоле="") Экспорт
ЧтениеДанных = Новый ЧтениеXML;
ЧтениеДанных.УстановитьСтроку(ДанныеФайла);
ЧтениеДанных.Прочитать();
Данные=ФабрикаXDTO.ПрочитатьXML(ЧтениеДанных);
Если ТипЗнч(Данные)=Тип("ОбъектXDTO") Тогда
СтруктураРезультат=Новый Структура();
Владелец="";
ВычСтрока="Структ";
ЗаписатьОбъектXDTOВСтруктуру(Данные,СтруктураРезультат,Владелец,ВычСтрока,Истина);
Иначе
ВызватьИсключение "XDTO. Что-то пошло не так....";
КонецЕсли;
КонецФункции // ПрочитатьФайлНаСервере(ДанныеФайла)
Функция, возвращающая структуру. Если не использовать ТаблицуЗначений, то полученную структуру можно смело загружать в JSon
Функция ПолучитьМассивИзСписка(Список)
ВремМассив=Новый ТаблицаЗначений;
АТутСписок=Новый СписокЗначений;
Для каждого Стр Из Список Цикл
НовСтр=ВремМассив.Добавить();
Для каждого ВСтр Из Стр.Свойства() Цикл
Если ВремМассив.Колонки.Найти(ВСтр.Имя)=Неопределено Тогда
ВремМассив.Колонки.Добавить(ВСтр.Имя);
Если ВСтр.ВерхняяГраница<>1 Тогда
АТутСписок.Добавить(ВСтр.Имя);
КонецЕсли;
КонецЕсли;
Если АТутСписок.НайтиПоЗначению(Встр.Имя)=Неопределено Тогда
НовСтр[ВСтр.Имя]=Стр.Получить(ВСтр);
Иначе
НовСтр[ВСтр.Имя]=ПолучитьМассивИзСписка(Стр[ВСтр.Имя]);
КонецЕсли;
КонецЦикла;
КонецЦикла;
Возврат ВремМассив;
КонецФункции // ПолучитьМассивИзСписка(Список)
Функция ЗаписатьОбъектXDTOВСтруктуру(Данные,Структ,Владелец,Знач ВычСтрока,ВложеннуюСтруктуруВТЗ=Ложь) Экспорт
Если ТипЗнч(Данные)=Тип("ОбъектXDTO")=Ложь Тогда
Сообщить("Это не XDTO");
Возврат Новый Структура();
КонецЕсли;
Коллекция=Данные.Свойства();
Если Коллекция.Количество()=0 Тогда
Владелец="";
Возврат Новый Структура();
Иначе
ВычСтрока=ВычСтрока+Владелец;
КонецЕсли;
ТТТ=Вычислить(ВычСтрока);
н=0;
Для каждого Элем Из Коллекция Цикл
н=н+1;
ТекКлюч=Элем.Имя;
Если Элем.ВерхняяГраница=1 Тогда
ЭлемДанные=Данные.Получить(Элем);
Если ТипЗнч(ЭлемДанные)=Тип("ОбъектXDTO") Тогда
Если ТТТ.Свойство(ТекКлюч)=Ложь Тогда
Владелец="."+ТекКлюч;
ТТТ.Вставить(ТекКлюч,Новый Структура);
ТТТ[ТекКлюч]=ЗаписатьОбъектXDTOВСтруктуру(Данные.Получить(Элем),Структ,Владелец,ВычСтрока,ВложеннуюСтруктуруВТЗ);
КонецЕсли;
ИначеЕсли ТипЗнч(Данные.Получить(Элем))=Тип("Строка") Тогда
ТТТ.Вставить(ТекКлюч,ЭлемДанные);
Иначе
А=1; //можно установить точку останова и посмотреть, что тут.....
КонецЕсли;
Иначе
АТутСписок=Новый СписокЗначений;
Если ВложеннуюСтруктуруВТЗ=Истина Тогда
ВремМассив=ПолучитьМассивИзСписка(Данные[ТекКлюч]);
Иначе
ВремМассив=Новый Массив;
Для каждого Стр Из Данные[ТекКлюч] Цикл
ВремСтр=Новый Структура();
Для каждого ВСтр Из Стр.Свойства() Цикл
Если ВСтр.ВерхняяГраница=1 Тогда
ВремСтр.Вставить(ВСтр.Имя,Стр.Получить(ВСтр));
Иначе
ВремСтр.Вставить(ВСтр.Имя,"Если есть желание, то можно дописать"); //если у кого-то список в списке.... может дописать :-)
КонецЕсли;
КонецЦикла;
ВремМассив.Добавить(ВремСтр);
КонецЦикла;
КонецЕсли;
ТТТ.Вставить(ТекКлюч,ВремМассив);
КонецЕсли;
КонецЦикла;
Возврат ТТТ;
КонецФункции // ЗаписатьОбъектXDTOВСтруктуру(Данные,Структ)
Функция для вывода структуры на печать.
Функция ПечатьСтруктуры(СтруктураРезультат,ЗаголовокШапки="Мой заголовок",СвернутьПоле="") Экспорт
Если ТипЗнч(СтруктураРезультат)=Тип("Структура") Тогда
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.ПолеСверху = 0;
ТабличныйДокумент.ПолеСлева = 0;
ТабличныйДокумент.ПолеСнизу = 0;
ТабличныйДокумент.ПолеСправа = 0;
ТабличныйДокумент.РазмерКолонтитулаСверху = 0;
ТабличныйДокумент.ОриентацияСтраницы = ОриентацияСтраницы.Ландшафт;
ТабличныйДокумент.АвтоМасштаб=Истина;
ТабличныйДокумент.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ДанныеДляСтруктуры";
Макет = ПолучитьМакет("ДанныеДляСтруктуры");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
Таб=ОбластьШапка.Параметры;
Таб.Заголовок=ЗаголовокШапки;
ТабличныйДокумент.Вывести(ОбластьШапка);
ТабличныйДокумент.НачатьАвтогруппировкуСтрок();
ВывестиСтруктуруНаПечать(СтруктураРезультат,ТабличныйДокумент,0,Макет,СвернутьПоле);
ТабличныйДокумент.ЗакончитьАвтогруппировкуСтрок();
Возврат ТабличныйДокумент;
Иначе
ВызватьИсключение "Структура. Что-то пошло не так....";
КонецЕсли;
КонецФункции // ПечатьСтруктуры()
Функция ВывестиСтруктуруНаПечать(Знач Данные,Таб,Знач Уровень,Макет,СвернутьПоле="") Экспорт
ОбластьСтрока = Макет.ПолучитьОбласть("Строка"+Формат(?(Уровень>5,5,Уровень),"ЧГ=0"));
ВлСтр=Макет.ПолучитьОбласть("ВложеннаяСтруктура|Айди");
ВлСтрК=Макет.ПолучитьОбласть("ВложеннаяСтруктура|Колонка");
ТЗКлюч=Макет.ПолучитьОбласть("ТЗКлюч|Айди");
ТЗРасш=Макет.ПолучитьОбласть("ТЗРасш|Айди");
Для каждого Стр Из Данные Цикл
ОбластьСтрока.Параметры.АйДи=Стр.Ключ;
Если ТипЗнч(Стр.Значение)=Тип("Структура") Тогда
ОбластьСтрока.Параметры.Значение="";
Если Стр.Ключ=СвернутьПоле Тогда
Таб.НачатьГруппуСтрок(СвернутьПоле,Ложь);
Таб.Вывести(ОбластьСтрока,Уровень,,Ложь);
Если Стр.Значение.Количество()>0 Тогда
ВывестиСтруктуруНаПечать(Стр.Значение,Таб,Уровень+1,Макет,СвернутьПоле)
КонецЕсли;
Таб.ЗакончитьГруппуСтрок();
Иначе
Таб.Вывести(ОбластьСтрока,Уровень);
Если Стр.Значение.Количество()>0 Тогда
ВывестиСтруктуруНаПечать(Стр.Значение,Таб,Уровень+1,Макет,СвернутьПоле)
КонецЕсли;
КонецЕсли;
ИначеЕсли ТипЗнч(Стр.Значение)=Тип("Массив") Тогда
ОбластьСтрока.Параметры.Значение="";
Таб.Вывести(ОбластьСтрока,Уровень);
Для каждого Элем Из Стр.Значение Цикл
Если ТипЗнч(Элем)=Тип("Структура") Тогда
Таб.Вывести(ВлСтр,Уровень+1,,Ложь);
Для каждого ЭС Из Элем Цикл
ВлСтрК.Параметры.Заполнить(ЭС);
Таб.Присоединить(ВлСтрК);
КонецЦикла;
ИначеЕсли ТипЗнч(Элем)=Тип("Строка") Тогда
ОбластьСтрока.Параметры.Значение=Элем;
Таб.Вывести(ОбластьСтрока,Уровень+1);
Иначе
сообщить(""+Стр.Ключ+": "+Стр.Значение);
КонецЕсли;
КонецЦикла;
ИначеЕсли ТипЗнч(Стр.Значение)=Тип("Строка") Тогда
ОбластьСтрока.Параметры.Значение=Стр.Значение;
Таб.Вывести(ОбластьСтрока,Уровень);
ИначеЕсли ТипЗнч(Стр.Значение)=Тип("ТаблицаЗначений") Тогда
ОбластьСтрока.Параметры.Значение="";
Таб.Вывести(ОбластьСтрока,Уровень);
ТЗ=Стр.Значение;
Если 1=2 Тогда
ТЗ=Новый ТаблицаЗначений;
КонецЕсли;
ТЗКлючК=Макет.ПолучитьОбласть("ТЗКлюч|Колонка");
Таб.Вывести(ТЗКлюч,Уровень+1,,Ложь);
Для каждого ТЗК Из ТЗ.Колонки Цикл
ТЗКлючК.Параметры.Ключ=ТЗК.Имя;
Таб.Присоединить(ТЗКлючК);
КонецЦикла;
ТЗКлючК=Макет.ПолучитьОбласть("ТЗЗначение|Колонка");
Для каждого СтрТЗ Из ТЗ Цикл
Таб.Вывести(ТЗКлюч,Уровень+1,,Ложь);
КолонкиС_ТЗ=Новый Структура();
Для каждого ТЗК Из ТЗ.Колонки Цикл
Если ТипЗнч(СтрТЗ[ТЗК.Имя])=Тип("ТаблицаЗначений") Тогда
ТЗКлючК.Параметры.Значение="Расшифровка ниже";
КолонкиС_ТЗ.Вставить(ТЗК.Имя,СтрТЗ[ТЗК.Имя]);
Таб.Присоединить(ТЗКлючК);
Иначе
ТЗКлючК.Параметры.Значение=СтрТЗ[ТЗК.Имя];
Таб.Присоединить(ТЗКлючК);
КонецЕсли;
КонецЦикла;
Если КолонкиС_ТЗ.Количество()>0 Тогда
ПервыйКлюч="";
Для каждого ТЗС Из КолонкиС_ТЗ Цикл
Если ПервыйКлюч=ТЗС.Ключ Тогда
Таб.Вывести(ТЗКлюч,Уровень+2,,Ложь);
Иначе
ПервыйКлюч=ТЗС.Ключ;
ТЗРасш.Параметры.Айди=ПервыйКлюч;
Таб.Вывести(ТЗРасш,Уровень+2,,Ложь);
Для каждого ТЗК Из ТЗС.Значение.Колонки Цикл
ТЗКлючК.Параметры.Значение=ТЗК.Имя;
Таб.Присоединить(ТЗКлючК);
КонецЦикла;
КонецЕсли;
Для каждого СтрТЗВл Из ТЗС.Значение Цикл
Таб.Вывести(ТЗКлюч,Уровень+2,,Ложь);
Для каждого ТЗК Из ТЗС.Значение.Колонки Цикл
ТЗКлючК.Параметры.Значение=СтрТЗВл[ТЗК.Имя];
Таб.Присоединить(ТЗКлючК);
КонецЦикла;
КонецЦикла;
КонецЦикла;
А=1;
КонецЕсли;
КонецЦикла;
Иначе
сообщить(""+Стр.Ключ+": "+Стр.Значение);
КонецЕсли;
КонецЦикла;
Возврат Таб;
КонецФункции // ВывестиСтруктуруНаПечать(Парам,Таб)
При выводе на печать есть ограничение, если у кого-то будет извращение, что списокXDTO, содержит поле со спискомXDTO, в котором будет ещё поле со списком XDTO, то при использовании таблицы значений (ТЗ) , третья и следующие ТЗ не будут выведены.
Пример макета: