() ojiojiowka, кусочек не жалко, но он большой и их два :)
Кусочек общего модуля ВерсионированиеОбъектов с исправлением ошибки в функции РазборПредставленияОбъектаXML():
// +AZ
Функция ПроверитьСоставныеТипы(ЧтениеXML,МетаданныеОбъекта,ИмяРеквизита,ЗначенияРеквизитов,ОписаниеРеквизита,УровеньЧтения,НовоеЗР,ВызовИзТЧ,ЗначениеПоля)
ОписаниеРеквизита = МетаданныеОбъекта.Реквизиты.Найти(ИмяРеквизита);
ЗначениеРеквизитаДобавлено = Ложь;
Если ЧтениеXML.КоличествоАтрибутов() > 0 Тогда
ЧтениеXML.Прочитать(); // Текст
ТипЗР = Неопределено;
ЗнРеквизита = Неопределено;
//НовоеЗР = ЗначенияРеквизитов.Добавить();
//НовоеЗР.НаименованиеРеквизита = ИмяРеквизита;
// Переберем возможные типы реквизита и попытаемся среди них найти реквизит с правильной ссылкой
Для каждого ОдинИзТипов Из ОписаниеРеквизита.Тип.Типы() Цикл
ТипЗР = ОдинИзТипов;
Попытка
УИД = Новый УникальныйИдентификатор(ЧтениеXML.Значение);
// если это не УИД, будет исключение
ЗнРеквизита = XMLЗначение(ТипЗР, ЧтениеXML.Значение);
Если ЗнРеквизита.ПолучитьОбъект() <> Неопределено Тогда
Прервать; // Это нужный тип из составного типа
КонецЕсли;
Исключение
// Это не УИД
ЗнРеквизита = ЧтениеXML.Значение;
Прервать;
КонецПопытки;
КонецЦикла;
Если ВызовИзТЧ Тогда
ЗначениеПоля = ЗнРеквизита;
Иначе
НовоеЗР = ЗначенияРеквизитов.Добавить();
НовоеЗР.НаименованиеРеквизита = ИмяРеквизита;
НовоеЗР.ЗначениеРеквизита = ЗнРеквизита;
НовоеЗР.Тип = ТипЗР;
КонецЕсли;
ЗначениеРеквизитаДобавлено = Истина;
Если ЧтениеXML.Имя <> "Row" И ЧтениеXML.Имя <> "" Тогда
УровеньЧтения = УровеньЧтения - 1;
КонецЕсли;
КонецЕсли;
Возврат ЗначениеРеквизитаДобавлено;
КонецФункции
// -AZ
Функция РазборПредставленияОбъектаXML(ДвоичныеДанные, Ссылка) Экспорт
// Содержит имя метаданного измененного объекта.
Перем ИмяОбъекта;
// Содержит положение маркера в дереве XML.
// Требуется для идентификации текущего элемента.
Перем УровеньЧтения;
// Содержат значения реквизитов справочников / документов.
ЗначенияРеквизитов = Новый ТаблицаЗначений;
ЗначенияРеквизитов.Колонки.Добавить("НаименованиеРеквизита");
ЗначенияРеквизитов.Колонки.Добавить("ЗначениеРеквизита");
ЗначенияРеквизитов.Колонки.Добавить("ТипРеквизита");
ЗначенияРеквизитов.Колонки.Добавить("Тип");
ТабличныеЧасти = Новый Соответствие;
ЧтениеXML = Новый ЧтениеFastInfoSet;
ЧтениеXML.УстановитьДвоичныеДанные(ДвоичныеДанные);
// Уровень позиции маркера в иерархии XML:
// 0 - уровень не задан
// 1 - первый элемент (имя объекта)
// 2 - описание реквизита или табличной части
// 3 - описание строки табличной части
// 4 - описание поля строки табличной части.
УровеньЧтения = 0;
МетаданныеОбъекта = Ссылка.Метаданные();
ТабличныеЧастиМТД = МетаданныеОбъекта.ТабличныеЧасти;
ТипЗначения = "";
ТипЗначенияПоляТЧ = "";
// Основной цикл разбора по XML.
Пока ЧтениеXML.Прочитать() Цикл
Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
УровеньЧтения = УровеньЧтения + 1;
Если УровеньЧтения = 1 Тогда // Указатель на первом элементе XML - корень XML.
ИмяОбъекта = ЧтениеXML.Имя;
ИначеЕсли УровеньЧтения = 2 Тогда // Указатель на втором уровне - это реквизит или имя табличной части.
ИмяРеквизита = ЧтениеXML.Имя;
ОписаниеРеквизита = Неопределено;
НовоеЗР = Неопределено;
ЗначениеПоля = Неопределено;
ЗначениеРеквизитаДобавлено = ПроверитьСоставныеТипы(ЧтениеXML,МетаданныеОбъекта,ИмяРеквизита,ЗначенияРеквизитов,ОписаниеРеквизита,УровеньЧтения,НовоеЗР,Ложь,ЗначениеПоля);
// Любой реквизит "может оказаться" табличной частью, поэтому на всякий случай его запомним.
ИмяТабличнойЧасти = ИмяРеквизита;
Если МетаданныеОбъекта.ТабличныеЧасти.Найти(ИмяТабличнойЧасти) <> Неопределено И ТабличныеЧасти[ИмяТабличнойЧасти] = Неопределено Тогда
ТабличныеЧасти.Вставить(ИмяТабличнойЧасти, Новый ТаблицаЗначений);
КонецЕсли;
Если Не ЗначениеРеквизитаДобавлено Тогда
НовоеЗР = ЗначенияРеквизитов.Добавить();
НовоеЗР.НаименованиеРеквизита = ИмяРеквизита;
КонецЕсли;
// +AZ
//Если ЧтениеXML.КоличествоАтрибутов() > 0 Тогда
// Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
// Если ЧтениеXML.ТипУзла = ТипУзлаXML.Атрибут
// И ЧтениеXML.Имя = "xsi:type" Тогда
// НовоеЗР.ТипРеквизита = ЧтениеXML.Значение;
//
// XMLТип = ЧтениеXML.Значение;
//
// Если Лев(XMLТип, 3) = "xs:" Тогда
// НовоеЗР.Тип = ИзXMLТипа(Новый ТипДанныхXML(Прав(XMLТип, СтрДлина(XMLТип)-3), "http://www.w3.org/2001/XMLSchema"));
// Иначе
// НовоеЗР.Тип = ИзXMLТипа(Новый ТипДанныхXML(XMLТип, ""));
// КонецЕсли;
//
// КонецЕсли;
// КонецЦикла;
//КонецЕсли;
// -AZ
Если Не ЗначениеЗаполнено(НовоеЗР.Тип) Тогда
// +AZ ОписаниеРеквизита получены значение выше по коду
// ОписаниеРеквизита = МетаданныеОбъекта.Реквизиты.Найти(НовоеЗР.НаименованиеРеквизита);
// -AZ
Если ОписаниеРеквизита = Неопределено Тогда
НаименованиеРеквизита = ПолучитьПредставлениеРеквизитаНаЯзыке(НовоеЗР.НаименованиеРеквизита);
Если ОбщегоНазначения.ЭтоСтандартныйРеквизит(МетаданныеОбъекта.СтандартныеРеквизиты, НаименованиеРеквизита) Тогда
ОписаниеРеквизита = МетаданныеОбъекта.СтандартныеРеквизиты[НаименованиеРеквизита];
КонецЕсли;
КонецЕсли;
Если ОписаниеРеквизита <> Неопределено
И ОписаниеРеквизита.Тип.Типы().Количество() = 1 Тогда
НовоеЗР.Тип = ОписаниеРеквизита.Тип.Типы()[0];
КонецЕсли;
КонецЕсли;
ИначеЕсли (УровеньЧтения = 3) И (ЧтениеXML.Имя = "Row") Тогда // Указатель на поле табличной части.
Если ТабличныеЧасти[ИмяТабличнойЧасти] = Неопределено Тогда
ТабличныеЧасти.Вставить(ИмяТабличнойЧасти, Новый ТаблицаЗначений);
КонецЕсли;
ТабличныеЧасти[ИмяТабличнойЧасти].Добавить();
ИначеЕсли УровеньЧтения = 4 Тогда // Указатель на поле табличной части.
ТипЗначенияПоляТЧ = "";
ИмяПоляТЧ = ЧтениеXML.Имя; //
// +AZ
ОписаниеРеквизита = Неопределено;
НовоеЗР = Неопределено;
ЗначениеПоля = Неопределено;
ЗначениеРеквизитаДобавлено = ПроверитьСоставныеТипы(ЧтениеXML,МетаданныеОбъекта,ИмяПоляТЧ,ЗначенияРеквизитов,ОписаниеРеквизита,УровеньЧтения,НовоеЗР,Истина,ЗначениеПоля);
// -AZ
Таблица = ТабличныеЧасти[ИмяТабличнойЧасти];
Если Таблица.Колонки.Найти(ИмяПоляТЧ)= Неопределено Тогда
Таблица.Колонки.Добавить(ИмяПоляТЧ);
КонецЕсли;
// +AZ
Если ЗначениеРеквизитаДобавлено Тогда
ПоследняяСтрока = ТабличныеЧасти[ИмяТабличнойЧасти].Получить(ТабличныеЧасти[ИмяТабличнойЧасти].Количество()-1);
ПоследняяСтрока[ИмяПоляТЧ] = ЗначениеПоля;
КонецЕсли;
//Если ЧтениеXML.КоличествоАтрибутов() > 0 Тогда
// Пока ЧтениеXML.ПрочитатьАтрибут() Цикл
// Если ЧтениеXML.ТипУзла = ТипУзлаXML.Атрибут
// И ЧтениеXML.Имя = "xsi:type" Тогда
// XMLТип = ЧтениеXML.Значение;
//
// Если Лев(XMLТип, 3) = "xs:" Тогда
// ТипЗначенияПоляТЧ = ИзXMLТипа(Новый ТипДанныхXML(Прав(XMLТип, СтрДлина(XMLТип)-3), "http://www.w3.org/2001/XMLSchema"));
// Иначе
// ТипЗначенияПоляТЧ = ИзXMLТипа(Новый ТипДанныхXML(XMLТип, ""));
// КонецЕсли;
//
// КонецЕсли;
// КонецЦикла;
//КонецЕсли;
// -AZ
КонецЕсли;
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента Тогда
УровеньЧтения = УровеньЧтения - 1;
ТипЗначения = "";
ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
Если (УровеньЧтения = 2) Тогда // значение реквизита
Попытка
НовоеЗР.ЗначениеРеквизита = ?(ЗначениеЗаполнено(НовоеЗР.Тип), XMLЗначение(НовоеЗР.Тип, ЧтениеXML.Значение), ЧтениеXML.Значение);
Исключение
НовоеЗР.ЗначениеРеквизита = ЧтениеXML.Значение;
КонецПопытки;
ИначеЕсли (УровеньЧтения = 4) Тогда // значение реквизита
ПоследняяСтрока = ТабличныеЧасти[ИмяТабличнойЧасти].Получить(ТабличныеЧасти[ИмяТабличнойЧасти].Количество()-1);
Если ТипЗначенияПоляТЧ = "" Тогда
ОписаниеРТЧ = Неопределено;
Если ТабличныеЧастиМТД.Найти(ИмяТабличнойЧасти) <> Неопределено Тогда
ОписаниеРТЧ = ТабличныеЧастиМТД[ИмяТабличнойЧасти].Реквизиты.Найти(ИмяПоляТЧ);
Если ОписаниеРТЧ <> Неопределено
И ОписаниеРТЧ.Тип.Типы().Количество() = 1 Тогда
ТипЗначенияПоляТЧ = ОписаниеРТЧ.Тип.Типы()[0];
КонецЕсли;
КонецЕсли;
КонецЕсли;
ПоследняяСтрока[ИмяПоляТЧ] = ?(ЗначениеЗаполнено(ТипЗначенияПоляТЧ), XMLЗначение(ТипЗначенияПоляТЧ, ЧтениеXML.Значение), ЧтениеXML.Значение);
КонецЕсли;
КонецЕсли;
КонецЦикла;
// Й-й этап: из списка реквизитов исключаем табличные части.
Для Каждого Элемент Из ТабличныеЧасти Цикл
ЗначенияРеквизитов.Удалить(ЗначенияРеквизитов.Найти(Элемент.Ключ));
КонецЦикла;
// ТабличныеЧастиМТД
Для Каждого ЭлементСоответствия Из ТабличныеЧасти Цикл
Таблица = ЭлементСоответствия.Значение;
Если Таблица.Колонки.Количество() = 0 Тогда
ТаблицаМТД = ТабличныеЧастиМТД.Найти(ЭлементСоответствия.Ключ);
Если ТаблицаМТД <> Неопределено Тогда
Для Каждого ОписаниеКолонки Из ТаблицаМТД.Реквизиты Цикл
Если Таблица.Колонки.Найти(ОписаниеКолонки.Имя)= Неопределено Тогда
Таблица.Колонки.Добавить(ОписаниеКолонки.Имя);
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЕсли;
КонецЦикла;
Результат = Новый Структура;
Результат.Вставить("Реквизиты", ЗначенияРеквизитов);
Результат.Вставить("ТабличныеЧасти", ТабличныеЧасти);
Возврат Результат;
КонецФункции
Показать