Статья о том, как НЕ надо использовать XML.
Попалась мне на глаза, как то раз, одна обработка выгрузки данных, которую хотелось бы прокомментировать. Текст представлен в том виде, в каком был мной найден, я поправил, разве что, лишь форматирование:
//*******************************************
перем xml_fso;
перем xml_file;
перем xml_СтекТегов;
перем xml_ТегОткрыт;
перем xml_Отступы;
перем Фвыгр экспорт, ИмяФайла экспорт, ПутьКФайлу экспорт, БД экспорт;
перем КодФирм;
//*******************************************
Процедура xml_СоздатьФайл(прм_ИмяФайла)
xml_fso=СоздатьОбъект("Scripting.FileSystemObject");
//создать файл, перезаписывая существующий.
xml_file=xml_fso.CreateTextFile(прм_ИмяФайла,-1, 0);
//Пишем заголовок XML.
xml_file.WriteLine("<?xml version=""1.0"" encoding=""windows-1251""?>");
xml_СтекТегов=СоздатьОбъект("СписокЗначений");
xml_Отступы="";
xml_ТегОткрыт=0;
КонецПроцедуры
//*******************************************
//Записывает начало элемента (тега XML). Имя можно указывать в угловых скобках.
//
Процедура xml_ЗаписатьНачалоЭлемента(прм_ИмяТега)
перем стр;
Если xml_ТегОткрыт=1 Тогда
xml_ТегОткрыт=0;
xml_file.WriteLine(">");
xml_Отступы=xml_Отступы+" ";
КонецЕсли;
стр=прм_ИмяТега;
стр=СтрЗаменить(стр, "<", "");
стр=СтрЗаменить(стр, ">", "");
xml_СтекТегов.ДобавитьЗначение(стр);
xml_file.Write(xml_Отступы+"<"+стр);
xml_ТегОткрыт=1;
КонецПроцедуры
//*******************************************
//Записывает атрибут (параметр) тега XML.
//
Процедура xml_ЗаписатьАтрибут(прм_ИмяАтрибута, прм_ЗначениеАтрибута)
Если xml_ТегОткрыт=0 Тогда
Сообщить("Перед записью атрибута необходимо записать начало элемента!","!");
а=10/0;
КонецЕсли;
стр=прм_ЗначениеАтрибута;
стр=СтрЗаменить(стр, "&", "&"+"a"+"m"+"p"+";");
стр=СтрЗаменить(стр, """", "&"+"q"+"u"+"o"+"t;");
стр=СтрЗаменить(стр, "<", "&"+"l"+"t"+";");
стр=СтрЗаменить(стр, ">", "&"+"g"+"t"+";");
стр=СтрЗаменить(стр, "'", "&"+"a"+"p"+"o"+"s;");
xml_file.Write(" "+прм_ИмяАтрибута+"="+""""+стр+"""");
КонецПроцедуры // xml_ЗаписатьЗаписатьАтрибут
//*******************************************
//Записывает конец элемента (тега XML). Имя закрываемого тега можно
//указывать в угловых скобках, а можно - не указывать вовсе.
//
Процедура xml_ЗаписатьКонецЭлемента(прм_ОжидаемоеИмяТега="")
перем стрИмяТега, а;
Если xml_СтекТегов.РазмерСписка()<1 Тогда
Сообщить("Попытка закрыть неоткрытый элемент!","!");
а=10/0;
КонецЕсли;
стрИмяТега=xml_СтекТегов.ПолучитьЗначение(xml_СтекТегов.РазмерСписка());
Если ПустаяСтрока(прм_ОжидаемоеИмяТега)=0 Тогда
стр=прм_ОжидаемоеИмяТега;
стр=СтрЗаменить(стр, "<", "");
стр=СтрЗаменить(стр, ">", "");
стр=СтрЗаменить(стр, "/", "");
Если стр<>стрИмяТега Тогда
Сообщить("Ожидается имя тега "+стр+", а закрыто "+стрИмяТега,"!"); а=10/0;
КонецЕсли;
КонецЕсли;
xml_СтекТегов.УдалитьЗначение(xml_СтекТегов.РазмерСписка());
Если xml_ТегОткрыт=1 Тогда
xml_ТегОткрыт=0;
xml_file.WriteLine("/>");
Возврат;
КонецЕсли;
xml_Отступы=лев(xml_Отступы, СтрДлина(xml_Отступы)-2);
xml_file.WriteLine(xml_Отступы+"</"+стрИмяТега+">");
КонецПроцедуры // xml_ЗаписатьКонецЭлемента
//*******************************************
//Закрывает открытый файл XML. После окончания работы
//с файлом его необходимо закрыть.
//
Функция xml_Закрыть()
xml_file.Close();
Если xml_СтекТегов.РазмерСписка()<>0 Тогда
Сообщить("Имеются незакрытые элементы XML!","!");
а=10/0;
КонецЕсли;
КонецФункции // xml_Закрыть
//*******************************************
Представленный выше набор процедур, служит для формирования файла выгрузки в формате XML и содержит процедуры создания тегов элементов и атрибутов в структуре Data Object Model [DOM], а также, некоторые элементы синтаксического контроля [функция xml_Закрыть()] полученного текста.
Пример — как пример, вполне, так себе, обычный. Сейчас, с модой на всякие XML, и учетом обязательных, в некоторых случаях, требований, многие так делают. Я бы сейчас не хотел заострять внимание на данной, конкретной, прямо таки небезупречной, реализации, сколько хотел бы поговорить о подобном подходе, в общем и целом. Представленный выше механизм является универсальным, поэтому, для примера, вполне можно воспользоваться им, чтобы выгрузить какой нибудь справочник. Текст процедуры, в данном случае, будет выглядеть примерно так:
//*******************************************
Процедура ВыгрузитьОбъект(Элемент)
xml_ЗаписатьНачалоЭлемента("<Код>");
xml_ЗаписатьАтрибут("Код",СокрЛП(Элемент.Код));
xml_ЗаписатьНачалоЭлемента("<Наименование>");
xml_ЗаписатьАтрибут("Наименование", СокрЛП(Элемент.Наименование));
xml_ЗаписатьКонецЭлемента("</Наименование>");
xml_ЗаписатьНачалоЭлемента("<ПолнНаименование>");
xml_ЗаписатьАтрибут("ПолнНаименование",СокрЛП(Элемент.КПП));
xml_ЗаписатьКонецЭлемента("</ПолнНаименование>");
xml_ЗаписатьНачалоЭлемента("<ИНН>");
xml_ЗаписатьАтрибут("ИНН",СокрЛП(Элемент.ИНН));
xml_ЗаписатьКонецЭлемента("</ИНН>");
xml_ЗаписатьНачалоЭлемента("<КПП>");
xml_ЗаписатьАтрибут("КПП",СокрЛП(Элемент.КПП));
xml_ЗаписатьКонецЭлемента("</КПП>");
xml_ЗаписатьНачалоЭлемента("<ЮрАдрес>");
xml_ЗаписатьАтрибут("ЮрАдрес",СокрЛП(Элемент.ЮрАдрес));
xml_ЗаписатьКонецЭлемента("</ЮрАдрес>");
xml_ЗаписатьНачалоЭлемента("<ФактАдрес>");
xml_ЗаписатьАтрибут("ФактАдрес",СокрЛП(Элемент.ФактАдрес));
xml_ЗаписатьКонецЭлемента("</ФактАдрес>");
xml_ЗаписатьНачалоЭлемента("<ВалютаДоговора>");
xml_ЗаписатьАтрибут("Код",СокрЛП(Элемент.ВалютаДоговора.Код));
xml_ЗаписатьАтрибут("Наименование",СокрЛП(Элемент.ВалютаДоговора.Наименование));
xml_ЗаписатьКонецЭлемента("</ВалютаДоговора>");
xml_ЗаписатьНачалоЭлемента("<ГлубинаКредита>");
xml_ЗаписатьАтрибут("ГлубинаКредита",СокрЛП(Элемент.ГлубинаКредита));
xml_ЗаписатьКонецЭлемента("</ГлубинаКредита>");
xml_ЗаписатьНачалоЭлемента("<Комментарий>");
xml_ЗаписатьАтрибут("Комментарий",СокрЛП(Элемент.Комментарий));
xml_ЗаписатьКонецЭлемента("</Комментарий>");
//конец табличной части
xml_ЗаписатьКонецЭлемента("</Код>");
КонецПроцедуры
//*******************************************
Процедура Выполнить()
xml_СоздатьФайл("C:\scripts\test1.xml");
спрКонтрагенты = СоздатьОбъект("Справочник.Контрагенты");
спрКонтрагенты.ВыбратьЭлементы();
Пока спрКонтрагенты.ПолучитьЭлемент() = 1 Цикл
ВыгрузитьОбъект(спрКонтрагенты.ТекущийЭлемент());
КонецЦикла;
xml_Закрыть();
КонецПроцедуры
//*******************************************
Здесь очень хорошо видно, что используемый нами набор процедур осуществляет только какую-то часть функций по синтаксическому контролю полученного файла. Контроль же за структурой полученного в результате выгрузки объекта 1С блока текста, полностью лежит на процедуре-обработчике данного типа объекта. То есть, таких процедур-обработчиков должно быть примерно столько-же, сколько выгружается типов объектов. И, примерно, столько-же, в процедуре загрузки данных.
Преобразование данных осуществляется как перед выгрузкой данных в рамках процедур-обработчиков, так, возможно, и при загрузке. Объекты в базе-приемнике, сопоставляются по значениям выгружаемых реквизитов. В данном примере [и в «боевом» варианте] данные справочника «Валюты» в реквизите «ВалютаДоговора» дублируются по числу элементов справочника «Контрагенты». Что не очень хорошо влияет на скорость формирования файла и объем этого самого файла.
Полученный в результате текст выглядит примерно так:
<?xml version="1.0" encoding="windows-1251"?>
<Код Код="00001">
<Наименование Наименование="ИП Иванов"/>
<ПолнНаименование ПолнНаименование="123"/>
<ИНН ИНН="123"/>
<КПП КПП="123"/>
<ЮрАдрес ЮрАдрес="его ю. адр"/>
<ФактАдрес ФактАдрес="его ф. адр"/>
<ВалютаДоговора Код="1" Наименование="Руб"/>
<ГлубинаКредита ГлубинаКредита="7"/>
<Комментарий Комментарий="1"/>
</Код>
<Код Код="00002">
<Наименование Наименование="ИП Петров"/>
<ПолнНаименование ПолнНаименование="123"/>
<ИНН ИНН="234"/>
<КПП КПП="123"/>
<ЮрАдрес ЮрАдрес="его ю. адр"/>
<ФактАдрес ФактАдрес="его ф. адр"/>
<ВалютаДоговора Код="1" Наименование="Руб"/>
<ГлубинаКредита ГлубинаКредита="7"/>
<Комментарий Комментарий="2"/>
</Код>
<Код Код="00003">
<Наименование Наименование="ИП Сидоров"/>
<ПолнНаименование ПолнНаименование="123"/>
<ИНН ИНН="345"/>
<КПП КПП="123"/>
<ЮрАдрес ЮрАдрес="его ю. адр"/>
<ФактАдрес ФактАдрес="его ф. адр"/>
<ВалютаДоговора Код="1" Наименование="Руб"/>
<ГлубинаКредита ГлубинаКредита="7"/>
<Комментарий Комментарий="3"/>
</Код>
Результат не является XML-файлом по определению [ссылка], так как не содержит корневого элемента. Выходит, что функции синтаксического контроля так и не справились со своей задачей. Значения реквизитов объекта располагается в реквизитах соответствующих элементов DOM, что делает информацию, представленную в файле, избыточной. С другой стороны, такой способ сохранения данных в файле выбран для того, чтобы иметь возможность сохранять данные реквизитов, которые, в свою очередь, сами являются объектами. В данном примере — это «ВалютаДоговора».
Вся процедура обмена, формирование файла выгрузки, его передача и анализ с последующей загрузкой будет выполняться медленно, ввиду избыточности информации, заключенной в файле. Анализатор XML-файлов, реализованный в обработке загрузки, не позволяет делать поиск и выборку элементов DOM — только последовательное сканирование и определение меток конца чтения элемента. Таким образом, обработки, использующие такой формат файла ничем не отличаются от таковых, если бы формат файла выгрузки был бы текстовым с разделителями.
Иными словами, формат файла выгрузки — изменился, а мышление программиста, писавшего эти обработки, — нет. Это печально…