#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда
#Область ОписаниеПеременных
Перем ЗаписьXML;
Перем КорневыеПространстваИмен;
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
Функция ДобавитьУзел(Родитель, Имя, Значение = Неопределено, МожетОтсутствовать = Ложь, МожетБытьНеопределено = Неопределено, Атрибуты = Неопределено, ПространстваИмен = Неопределено) Экспорт
Если Родитель = Неопределено Тогда
Родитель = ДеревоXML;
КонецЕсли;
Если Не ЗначениеЗаполнено(Имя) Тогда
Возврат Неопределено;
КонецЕсли;
Если МожетБытьНеопределено = Неопределено Тогда
МожетБытьНеопределено = (Значение = Неопределено Или Значение = Null);
КонецЕсли;
Узел = Родитель.Строки.Добавить();
Узел.Имя = Имя;
Узел.Атрибуты = Атрибуты;
Узел.ПространстваИмен = ПространстваИмен;
Узел.МожетОтсутствовать = МожетОтсутствовать;
Узел.МожетБытьНеопределено = МожетБытьНеопределено;
Если МожетБытьНеопределено И Не ЗначениеЗаполнено(Значение) Тогда
Узел.Текст = Неопределено;
Иначе
Тип = ТипЗнч(Значение);
Если Тип = Тип("Строка") Тогда
Узел.Текст = Значение;
ИначеЕсли Тип = Тип("Дата") И ЗначениеЗаполнено(ФорматДат) Тогда
Узел.Текст = Формат(Значение, ФорматДат);
Иначе
Узел.Текст = XMLСтрока(Значение);
КонецЕсли;
КонецЕсли;
Возврат Узел;
КонецФункции
Процедура ДобавитьПространствоИмен(Узел, Префикс, URI) Экспорт
Если Узел = Неопределено Тогда
ПространстваИмен = КорневыеПространстваИмен;
Иначе
ПространстваИмен = Узел.ПространстваИмен;
Если ПространстваИмен = Неопределено Тогда
ПространстваИмен = Новый СписокЗначений;
Узел.ПространстваИмен = ПространстваИмен;
КонецЕсли;
КонецЕсли;
ПространстваИмен.Добавить(Префикс, URI);
КонецПроцедуры
Процедура ДобавитьАтрибут(Узел, Имя, Значение) Экспорт
Атрибуты = Узел.Атрибуты;
Если Атрибуты = Неопределено Тогда
Атрибуты = Новый Соответствие;
Узел.Атрибуты = Атрибуты;
КонецЕсли;
Атрибуты.Вставить(Имя, Значение);
КонецПроцедуры
Функция НачатьЗаписьВСтрокуXML(ЗаписатьОбъявлениеXML = Истина, Кодировка = "UTF-8") Экспорт
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.УстановитьСтроку(Кодировка);
Если ЗаписатьОбъявлениеXML Тогда
ЗаписьXML.ЗаписатьОбъявлениеXML();
КонецЕсли;
Для Каждого ЭлементСписка Из КорневыеПространстваИмен Цикл
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен(ЭлементСписка.Значение, ЭлементСписка.Представление);
КонецЦикла;
Возврат ЗаписьXML;
КонецФункции
Процедура ЗаписатьДеревоXML() Экспорт
Если ЗаписьXML = Неопределено Тогда
НачатьЗаписьВСтрокуXML();
КонецЕсли;
Для Каждого Узел Из ДеревоXML.Строки Цикл
ЗаписатьУзелXML(Узел);
КонецЦикла;
ДеревоXML.Строки.Очистить();
КонецПроцедуры
Функция СтрокаXML() Экспорт
ЗаписатьДеревоXML();
Возврат ЗаписьXML.Закрыть();
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Процедура ЗаписатьУзелXML(Узел)
Если Не ТребуетсяВыгрузитьУзел(Узел) Тогда
Возврат;
КонецЕсли;
ЗаписьXML.ЗаписатьНачалоЭлемента(Узел.Имя);
Если Узел.Атрибуты <> Неопределено Тогда
Для Каждого КлючИЗначение Из Узел.Атрибуты Цикл
ЗаписьXML.ЗаписатьАтрибут(КлючИЗначение.Ключ, КлючИЗначение.Значение);
КонецЦикла;
КонецЕсли;
Если Узел.ПространстваИмен <> Неопределено Тогда
Для Каждого ЭлементСписка Из Узел.ПространстваИмен Цикл
ЗаписьXML.ЗаписатьСоответствиеПространстваИмен(ЭлементСписка.Значение, ЭлементСписка.Представление);
КонецЦикла;
КонецЕсли;
Если Узел.Текст <> Неопределено Тогда
ЗаписьXML.ЗаписатьТекст(Узел.Текст);
ИначеЕсли (Узел.Атрибуты = Неопределено Или Узел.Атрибуты.Количество() = 0)
И Узел.Строки.Количество() = 0 Тогда
ЗаписьXML.ЗаписатьАтрибут("xsi:nil", "true");
КонецЕсли;
Для Каждого ВложенныйУзел Из Узел.Строки Цикл
ЗаписатьУзелXML(ВложенныйУзел);
КонецЦикла;
ЗаписьXML.ЗаписатьКонецЭлемента();
КонецПроцедуры
Функция ТребуетсяВыгрузитьУзел(Узел)
Возврат Не Узел.МожетОтсутствовать
Или ЗначениеЗаполнено(Узел.Текст)
Или ОдинИзВложенныхУзловЗаполнен(Узел);
КонецФункции
Функция ОдинИзВложенныхУзловЗаполнен(Узел)
Для Каждого ВложенныйУзел Из Узел.Строки Цикл
Если ЗначениеЗаполнено(ВложенныйУзел.Текст) Или ОдинИзВложенныхУзловЗаполнен(ВложенныйУзел) Тогда
Возврат Истина;
КонецЕсли;
КонецЦикла;
Возврат Ложь;
КонецФункции
#КонецОбласти
#Область Инициализация
ДеревоXML.Колонки.Добавить("Имя", Новый ОписаниеТипов("Строка"));
ДеревоXML.Колонки.Добавить("Текст", Новый ОписаниеТипов("Строка, Булево"));
ДеревоXML.Колонки.Добавить("Атрибуты");
ДеревоXML.Колонки.Добавить("ПространстваИмен");
ДеревоXML.Колонки.Добавить("МожетОтсутствовать", Новый ОписаниеТипов("Булево"));
ДеревоXML.Колонки.Добавить("МожетБытьНеопределено", Новый ОписаниеТипов("Булево"));
ФорматДат = "ДФ=yyyy-MM-dd";
ВыгружатьПустые = Истина;
КорневыеПространстваИмен = Новый СписокЗначений
#КонецОбласти
#Иначе
ВызватьИсключение НСтр("ru = 'Недопустимый вызов объекта на клиенте.'");
#КонецЕсли