Для работы с WEB-сервисами часто надо передавать данные сложной формы, поэтому сделал не очень красивый механизм сохранения структуры данных в XML и обратное его преобразование.
Для того, чтобы данные однозначно распознались, надо создать тип XDTO, на основании которого будет создана структура, но так как для каждого отдельного случая нет желания создавать отдельный XDTO-пакет, то попытался сделать универсальный механизм.
При переводе структуры в XML в элементе Value передается тип в атрибуте "xsi:type". По нему определяем тип передаваемого элемента. Можно использовать элементарные типы, вложенные структуры и массивы. Для использования других типов надо дописать код.
Код модуля:
#Область XML
Функция ПолучитьСоответствиеТиповXML()
СоответствиеТипов = Новый Соответствие();
СоответствиеТипов.Вставить("xs:dateTime",Тип("Дата"));
СоответствиеТипов.Вставить("xs:decimal",Тип("Число"));
СоответствиеТипов.Вставить("xs:int",Тип("Число"));
СоответствиеТипов.Вставить("xs:integer",Тип("Число"));
СоответствиеТипов.Вставить("xs:float",Тип("Число"));
СоответствиеТипов.Вставить("xs:boolean", Тип("Булево"));
Возврат СоответствиеТипов
КонецФункции
// СтруктураДанных типа Структурра
// Возможно использование вложенных структур и массивов
Функция СтруктуруВXML(СтруктураДанных) Экспорт
ОбъектXDTO = СериализаторXDTO.ЗаписатьXDTO(СтруктураДанных);
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку();
ФабрикаXDTO.ЗаписатьXML(ЗаписьXML, ОбъектXDTO);
XML = ЗаписьXML.Закрыть();
Возврат XML;
КонецФункции
// Тип элемента определяется по атрибуту "xsi:type" элемента Value
// Если тип не определен, то значение будет текстового типа
Функция ИзXMLВСтруктуру(ТекстXML) Экспорт
Перем Результат;
СоответствиеТипов = ПолучитьСоответствиеТиповXML();
Результат = Новый Структура();
ЗаписьXML = Новый ЧтениеXML;
ЗаписьXML.УстановитьСтроку(ТекстXML);
ЗаписьXML.Прочитать();
Результат = ПолучитьСтруктуру(ЗаписьXML, СоответствиеТипов, ЗаписьXML.Имя);
Возврат Результат;
КонецФункции
Функция ПолучитьСтруктуру(ЗаписьXML, СоответствиеТипов, знач ИмяРодительскогоЭлемента)
Результат =Новый Структура;
КонецСтруктуры = Ложь;
Пока Не КонецСтруктуры Цикл
Если НЕ ЗаписьXML.Прочитать() Тогда
Прервать;
КонецЕсли;
Если ЗаписьXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЗаписьXML.Имя = "Property" Тогда
ИмяЭлемента = ЗаписьXML.ЗначениеАтрибута("name");
ЗаписьXML.Прочитать(); // читаем значение (value)
ЗначениеЭлемента = ПолучитьЗначениеСвойства(ЗаписьXML, СоответствиеТипов); //получаем значение value
ЗаписьXML.Прочитать(); //закрыть value
Результат.Вставить(ИмяЭлемента, ЗначениеЭлемента);
//не читаем запись, так как при этом возникает ошибка при чтении вложенных структур
//ЗаписьXML.Прочитать(); //закрываем Property
ИначеЕсли ЗаписьXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЗаписьXML.Имя = ИмяРодительскогоЭлемента Тогда
КонецСтруктуры = Истина;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПолучитьМассив(ЗаписьXML, СоответствиеТипов)
Результат = Новый Массив();
КонецМассива = Ложь;
Пока Не КонецМассива Цикл
Если НЕ ЗаписьXML.Прочитать() Тогда
Прервать;
КонецЕсли;
Если ЗаписьXML.ТипУзла = ТипУзлаXML.НачалоЭлемента И ЗаписьXML.Имя = "Value" Тогда
ЗначениеЭлемента = ПолучитьЗначениеСвойства(ЗаписьXML, СоответствиеТипов);
Результат.Добавить(ЗначениеЭлемента);
ИначеЕсли ЗаписьXML.ТипУзла = ТипУзлаXML.КонецЭлемента И ЗаписьXML.Имя = "Value" Тогда
КонецМассива = Истина;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
Функция ПолучитьЗначениеСвойства(ЗаписьXML, Знач СоответствиеТипов)
Перем ЗначениеЭлемента, Тип, ТипЭлемента;
ТипЭлемента = ЗаписьXML.ЗначениеАтрибута("xsi:type");
Если ТипЭлемента = "Structure" Тогда
ЗначениеЭлемента = ПолучитьСтруктуру(ЗаписьXML, СоответствиеТипов, ЗаписьXML.Имя);
ИначеЕсли ТипЭлемента = "Array" Тогда
ЗначениеЭлемента = ПолучитьМассив(ЗаписьXML, СоответствиеТипов);
Иначе
Тип = СоответствиеТипов.Получить(ТипЭлемента);
ЗаписьXML.Прочитать();
ЗначениеЭлемента = ЗаписьXML.Значение;
Если Тип <> Неопределено Тогда
ЗначениеЭлемента = XMLЗначение(Тип,ЗначениеЭлемента);
КонецЕсли;
КонецЕсли;
Возврат ЗначениеЭлемента;
КонецФункции
#КонецОбласти
|