Упрощаем чтение XML или любите СП — источник знаний (2)



Функция преобразования xml в структуру

 

Однаждый Джоель Мозес (англ. Joel Moses) сказал «APL как красивый бриллиант — безупречный, симметричный. Но вы ничего не можете к нему добавить. Если вы попытаетесь приклеить к нему другой алмаз — вы не получите бóльший алмаз. Лисп же — это ком грязи. Добавь еще и он останется комом грязи — он все еще будет выглядеть как Лисп.» Для меня, кроме лиспа, таким комом грязи стал XML. На протяжении долгого времени на эти значки < и > натягивают все больше и больше семантики. Появляются страшные слова —  DTD,  xsd, xslt, RDF …. Сегодня уже вовсю идет подготовка к Xforms, и кто знает что еще прикрутят к этому формату завтра? Кассанрой работать всегда тяжело, но одно знаю точно — XML останется XML — заголовок и корневой элемент, открывающие и закрывающие тэги, текстовое представление — останется всегда. А раз так — то вечным будет вопрос — как прочитать XML и работать с ним?

Многие пишут свои универсальные функции которые разбирают XML в дерево, в таблицу значений, в массив или как в этой заметке — в структуру. У всех этих способов есть свои плюсы и минусы.

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

Минусы — время работы, объем потребляемой памяти. Поэтому для чтения больших файлов (более 5 kb) слабо подходит.

 

Для примера используется такое определение XSD

 

и вот такой xml для теста

 

Код для преобразования —

 

Функция xdto2struct(XDTO)
структураОбъекта = новый Структура;
Для каждого х Из XDTO.свойства() Цикл
Попытка
// пусть так определяется что это список. Может и лучше можно, не знаю.
ПрочитаноеЗначение= XDTO.ПолучитьСписок(х);
Исключение
ПрочитаноеЗначение= XDTO.Получить(х);
КонецПопытки;
типЭлемента = типЗнч(ПрочитаноеЗначение);
если  типЭлемента = тип("ОбъектXDTO") тогда
структураОбъекта.Вставить(х.Имя,xdto2struct(ПрочитаноеЗначение));
иначеесли типЭлемента  = тип("СписокXDTO") тогда
структураОбъекта.Вставить(х.Имя, list2array(ПрочитаноеЗначение));
иначе
/// простое значение
структураОбъекта.Вставить(х.Имя,ПрочитаноеЗначение);
КонецЕсли;
КонецЦикла;
Возврат структураОбъекта;
КонецФункции

функция list2array(listXdto)
массивВозврата = новый Массив;
для каждого у из listXdto цикл
массивВозврата.Добавить(новый Структура("Тип,Значение",ТипВСтруктуру(у.тип()),xdto2struct(у)));
конецЦикла;
возврат массивВозврата;
КонецФункции

Функция ТипВСтруктуру(типРазбора)
Возврат  Новый Структура("URI,имя",типРазбора.URIПространстваИмен ,типРазбора.Имя);
КонецФункции

 

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

Вот так будет выглядеть корневой элемент

 

На этом скриншоте — элементы массива (кстати, если XML  — простой (нет пересекающихся имен типов) можно легко отказаться от описания типа)

 

 

Так выглядит загруженный элемент one (обратите внимание что тэг age — уже приведен к числу, согласно схемы)

 

 

 

В обработке прикрепленной к заметке — тот же самый код (плюс несколько несложных сервисных функций)

 

 

6 Comments

  1. Yashazz

    Пхе. В своё время я написал функцию-универсалку, которая любой XDTO-объект раздербанивает в коллекции 1С (например, в дерево, в строках которого массивы, или структуры, или ещё что, короче, полностью соответствуя структуре исходного объекта). Короче, усложнённый вариант вашей версии. Разумеется, исходя из его URI и фабрики. Но и то публиковать не стал, ибо техническая вспомогательная хрень.

    А вы, автор, совсем простые вещи эдак разжёвываете… Зачем? Всё равно, что перебор элементов массива объяснять статьёй на 5 страниц.

    Кстати, конечно же, можно определять факт «списочности» иначе. Например, навскидку, так:

    Если СвойствоXDTO.НижняяГраница=0 и СвойствоXDTO.ВерхняяГраница=-1 Тогда // списочный

    ну или учитывать, что кол-во в списке может быть ограничено, и тогда уж исходя из него ))

    Reply
  2. so-quest

    вы абсолютно во всем правы. Для себя скачал вашу разработку http://infostart.ru/public/203514/ буду неделю изучать и приобщаться к мудрости.

    И да, — в заголовке ясно указано — любите СП. Но чукча же не читатель…

    Reply
  3. iov

    В закладочки на память. Автору спасибо очень полезная статья.

    Reply
  4. WEBBY

    Здорово! Спасибо автору!

    Reply
  5. GVasiliy

    Автор, поменяйте «попытку» на проверку:

    ТипЗнч( … ) = Тип(«СписокXDTO»)

    ТипЗнч( … ) = Тип(«ОбъектXDTO»).

    Reply
  6. so-quest

    да я бы с удовольствием, но анализируется не значение, а свойство. и все обламывает…

    В (0) опытные разработчики советуют вариант без попытки (там тоже есть ограничения)

    в принципе мне хватало всегда проверки

    Если х.НижняяГраница=х.ВерхняяГраница и х.ВерхняяГраница=1 Тогда // наверное список

    но подобная практика пару раз приводила к ошибкам (правда на 8.1 ) поэтому здесь и сделал через попытку. С точки зрения быстродействия вариант с попыткой проходит — потери не большие, да и читается проще

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *