1+ #Использовать logos
2+
3+ Перем Лог ;
4+ Перем ИмяПоследнегоАтрибута ;
5+ Перем УпроститьЭлементы ;
6+
7+ Процедура ПриСозданииОбъекта (Упростить = Истина )
8+
9+ УпроститьЭлементы = Истина ;
10+
11+ Если ЗначениеЗаполнено (Упростить) Тогда
12+ УпроститьЭлементы = Упростить;
13+ КонецЕсли ;
14+
15+ Лог = Логирование.ПолучитьЛог("oscript.lib.xml-parser" );
16+
17+ КонецПроцедуры
18+
19+ // Выполняет чтение данных xml в соответствие
20+ //
21+ // Параметры:
22+ // ПутьКФайлу - Строка - путь к файлу с данными xml
23+ //
24+ // Возвращаемое значение:
25+ // Соответствие, Структура - результат чтения данных xml
26+ //
27+ Функция ПрочитатьИзФайла (Знач ПутьКФайлу ) Экспорт
28+
29+ Чтение = Новый ЧтениеXML;
30+ Чтение.ОткрытьФайл(ПутьКФайлу);
31+
32+ Результат = ПрочитатьXML (Чтение);
33+
34+ Чтение.Закрыть();
35+
36+ Возврат Результат;
37+
38+ КонецФункции
39+
40+ // Выполняет сериализацию данных в файла
41+ //
42+ // Параметры:
43+ // ДанныеЗаписиXML - Соответствие, Массив, Структура, Число, Строка. Дата - данные для сериализации в XML
44+ // ПутьКФайлу - Строка - путь к файлу с данными xml
45+ // ЗаписатьОбъявлениеXML - Булево - признак добавления записи объявления XML
46+ //
47+ Процедура ЗаписатьВФайл (ДанныеЗаписиXML , Знач ПутьКФайлу , Знач ЗаписатьОбъявлениеXML = Ложь ) Экспорт
48+
49+ ЗаписьXML = Новый ЗаписьXML;
50+ ЗаписьXML.ОткрытьФайл(ПутьКФайлу);
51+
52+ Если ЗаписатьОбъявлениеXML Тогда
53+ ЗаписьXML.ЗаписатьОбъявлениеXML();
54+ КонецЕсли ;
55+
56+ ЗаписатьXML (ЗаписьXML, ДанныеЗаписиXML);
57+
58+ ЗаписьXML.Закрыть();
59+
60+ КонецПроцедуры
61+
62+ // Выполняет чтение и десериализацию данных из XML
63+ //
64+ // Параметры:
65+ // ЧтениеXML - ЧтениеXML - <описание параметра>
66+ // ИмяКорневогоУзла - Строка - имя текущего узла, для вызова рекурсии
67+ //
68+ // Возвращаемое значение:
69+ // Соответствие, Структура - результат чтения данных xml
70+ //
71+ Функция ПрочитатьXML (Знач ЧтениеXML , Знач ИмяКорневогоУзла = "" ) Экспорт
72+
73+ РезультатЧтения = Новый Структура;
74+ Атрибуты = Новый Соответствие;
75+ Элементы = Новый Соответствие;
76+
77+ РезультатЧтения.Вставить("_Атрибуты" , Атрибуты);
78+ РезультатЧтения.Вставить("_Элементы" , Элементы);
79+
80+ Лог.Отладка("Начинаю чтение узла <%1> из XML." , ЧтениеXML.ЛокальноеИмя);
81+
82+ ПрочитатьАтрибуты(ЧтениеXML, Атрибуты);
83+
84+ Если Не ЧтениеXML.ТипУзла = ТипУзлаXML.КонецСущности Тогда
85+ ПрочитатьУзлы(ЧтениеXML, РезультатЧтения, ИмяКорневогоУзла);
86+ КонецЕсли ;
87+
88+ УпроститьРезультатЧтения(РезультатЧтения);
89+
90+ Лог.Отладка("Чтение узла <%1> закончено." , ЧтениеXML.ЛокальноеИмя);
91+
92+ Возврат РезультатЧтения;
93+
94+ КонецФункции
95+
96+ // Выполняет сериализацию данных в XML
97+ //
98+ // Параметры:
99+ // ЗаписьXML - ЗаписьXML - подготовленная запись ЗаписьXML
100+ // ДанныеЗаписиXML - Соответствие, Массив, Структура, Число, Строка. Дата - данные для сериализации в XM
101+ //
102+ Процедура ЗаписатьXML (Знач ЗаписьXML , Знач ДанныеЗаписиXML ) Экспорт
103+
104+ ЗаписатьЗначениеXML(ЗаписьXML, ДанныеЗаписиXML);
105+
106+ КонецПроцедуры
107+
108+ #Область Запись_данных_XML
109+
110+ Процедура ЗаписатьЗначениеXML (Знач ЗаписьXML , Знач ДанныеЗаписиXML , Знач ИмяКорневогоУзла = "" )
111+
112+ НачатьЗаписьЭлемента = НЕ ПустаяСтрока (ИмяКорневогоУзла);
113+
114+ Если НачатьЗаписьЭлемента Тогда
115+ ЗаписьXML.ЗаписатьНачалоЭлемента(XMLСтрока (ИмяКорневогоУзла));
116+ КонецЕсли ;
117+
118+ ТипДанныеЗаписиXML = ТипЗнч (ДанныеЗаписиXML);
119+
120+ Если ТипДанныеЗаписиXML = Тип ("Массив" ) Тогда
121+ ЗаписатьМассивВXML(ЗаписьXML, ДанныеЗаписиXML);
122+ ИначеЕсли ТипДанныеЗаписиXML = Тип ("Соответствие" )
123+ ИЛИ ТипДанныеЗаписиXML = Тип ("Структура" ) Тогда
124+ ЗаписатьСоответствиеВXML(ЗаписьXML, ДанныеЗаписиXML);
125+ ИначеЕсли ЭтоПростойТип(ТипДанныеЗаписиXML) Тогда
126+
127+ ЗаписатьТекст(ЗаписьXML, ДанныеЗаписиXML);
128+
129+ КонецЕсли ;
130+
131+ Если НачатьЗаписьЭлемента Тогда
132+ ЗаписьXML.ЗаписатьКонецЭлемента();
133+ КонецЕсли ;
134+
135+ КонецПроцедуры
136+
137+ Функция ЭтоПростойТип (Знач ТипДанных )
138+
139+ Возврат ТипДанных = Тип ("Число" )
140+ ИЛИ ТипДанных = Тип ("Строка" )
141+ ИЛИ ТипДанных = Тип ("Булево" )
142+ ;
143+
144+ КонецФункции
145+
146+ Процедура ЗаписатьАтрибуты (ЗаписьXML , ДанныеАтрибутов )
147+
148+ Если ДанныеАтрибутов.Количество() = 0 Тогда
149+ Возврат ;
150+ КонецЕсли ;
151+
152+ Для каждого КлючЗначение Из ДанныеАтрибутов Цикл
153+
154+ ЗаписьXML.ЗаписатьАтрибут(XMLСтрока (КлючЗначение.Ключ), XMLСтрока (КлючЗначение.Значение));
155+
156+ КонецЦикла ;
157+
158+ КонецПроцедуры
159+
160+ Процедура ЗаписатьСекцияCDATA (ЗаписьXML , ДанныеСекцияCDATA )
161+
162+ Если НЕ ЗначениеЗаполнено (ДанныеСекцияCDATA) Тогда
163+ Возврат ;
164+ КонецЕсли ;
165+
166+ ЗаписьXML.ЗаписатьСекциюCDATA(ДанныеСекцияCDATA);
167+
168+ КонецПроцедуры
169+
170+ Процедура ЗаписатьКомментарий (ЗаписьXML , Комментарий )
171+
172+ Если НЕ ЗначениеЗаполнено (Комментарий) Тогда
173+ Возврат ;
174+ КонецЕсли ;
175+
176+ ЗаписьXML.ЗаписатьКомментарий(XMLСтрока (Комментарий));
177+
178+ КонецПроцедуры
179+
180+ Процедура ЗаписатьТекст (ЗаписьXML , Текст )
181+
182+ Если НЕ ЗначениеЗаполнено (Текст) Тогда
183+ Возврат ;
184+ КонецЕсли ;
185+
186+ ЗаписьXML.ЗаписатьТекст(XMLСтрока (Текст));
187+
188+ КонецПроцедуры
189+
190+ Процедура ЗаписатьМассивВXML (ЗаписьXML , Знач ДанныеМассива )
191+
192+ Для каждого ЭлементМассива Из ДанныеМассива Цикл
193+ ЗаписатьЗначениеXML(ЗаписьXML, ЭлементМассива);
194+ КонецЦикла ;
195+
196+ КонецПроцедуры
197+
198+ Процедура ЗаписатьСоответствиеВXML (ЗаписьXML , ДанныеСоответствия )
199+
200+ Для каждого КлючЗначение Из ДанныеСоответствия Цикл
201+
202+ Если КлючЗначение.Ключ = "_Атрибуты" Тогда
203+ ЗаписатьАтрибуты(ЗаписьXML, КлючЗначение.Значение);
204+ Продолжить ;
205+ КонецЕсли ;
206+
207+ Если КлючЗначение.Ключ = "_Комментарий" Тогда
208+ ЗаписатьКомментарий(ЗаписьXML, КлючЗначение.Значение);
209+ Продолжить ;
210+ КонецЕсли ;
211+
212+ Если КлючЗначение.Ключ = "_CDATA" Тогда
213+ ЗаписатьСекцияCDATA(ЗаписьXML, КлючЗначение.Значение);
214+ Продолжить ;
215+ КонецЕсли ;
216+
217+ Если КлючЗначение.Ключ = "_Значение" Тогда
218+ ЗаписатьТекст(ЗаписьXML, КлючЗначение.Значение);
219+ Продолжить ;
220+ КонецЕсли ;
221+
222+ Если КлючЗначение.Ключ = "_Элементы" Тогда
223+ ЗаписатьЗначениеXML(ЗаписьXML, КлючЗначение.Значение);
224+ Продолжить ;
225+ КонецЕсли ;
226+
227+ ЗаписатьЗначениеXML(ЗаписьXML, КлючЗначение.Значение, КлючЗначение.Ключ);
228+
229+ КонецЦикла ;
230+
231+ КонецПроцедуры
232+
233+ #КонецОбласти
234+
235+ #Область Чтение_данных_XML
236+
237+ Процедура УпроститьРезультатЧтения (РезультатЧтения )
238+
239+ Если НЕ УпроститьЭлементы Тогда
240+ Возврат ;
241+ КонецЕсли ;
242+
243+ Если РезультатЧтения["_Атрибуты" ].Количество() = 0 Тогда
244+ РезультатЧтения.Удалить("_Атрибуты" );
245+ КонецЕсли ;
246+
247+ Если РезультатЧтения["_Элементы" ].Количество() = 0 Тогда
248+ РезультатЧтения.Удалить("_Элементы" );
249+ КонецЕсли ;
250+
251+ МожноУпростить = РезультатЧтения.Количество() = 1 ;
252+
253+ Если МожноУпростить Тогда
254+ Если РезультатЧтения.Свойство("_Значение" ) Тогда
255+ РезультатЧтения = РезультатЧтения._Значение;
256+ ИначеЕсли РезультатЧтения.Свойство("_Элементы" ) Тогда
257+ РезультатЧтения = РезультатЧтения._Элементы;
258+ КонецЕсли ;
259+ КонецЕсли ;
260+
261+ КонецПроцедуры
262+
263+ Процедура ПрочитатьАтрибуты (Знач ЧтениеXML , Атрибуты )
264+
265+ Если ЧтениеXML.КоличествоАтрибутов() = 0 Тогда
266+ ИмяПоследнегоАтрибута = Неопределено ;
267+ Возврат ;
268+ КонецЕсли ;
269+
270+ Для ИндексАтрибута = 0 По ЧтениеXML.КоличествоАтрибутов() - 1 Цикл
271+
272+ ИмяАтрибута = ЧтениеXML.ИмяАтрибута(ИндексАтрибута);
273+ ЗначениеАтрибута = ЧтениеXML.ЗначениеАтрибута(ИмяАтрибута);
274+
275+ Лог.Отладка("Прочитано значение <%1> атрибута <%2>" , ЗначениеАтрибута, ИмяАтрибута);
276+ Атрибуты.Вставить(СокрЛП (ИмяАтрибута), СокрЛП (ЗначениеАтрибута));
277+ ИмяПоследнегоАтрибута = ЧтениеXML.Имя;
278+ КонецЦикла ;
279+
280+ КонецПроцедуры
281+
282+ Процедура ПрочитатьУзлы (Знач ЧтениеXML , КорневойУзел , Знач ИмяКорневогоУзла )
283+
284+ Пока ЧтениеXML.Прочитать() Цикл
285+
286+ Лог.Отладка("Тип узла <%1>" , ЧтениеXML.ТипУзла);
287+ Лог.Отладка("Имя узла <%1>" , ЧтениеXML.ЛокальноеИмя);
288+
289+ Если ЧтениеXML.ТипУзла = ТипУзлаXML.КонецЭлемента
290+ И ЧтениеXML.ЛокальноеИмя = ИмяКорневогоУзла Тогда
291+ Прервать ;
292+ КонецЕсли ;
293+
294+ Если ЧтениеXML.ТипУзла = ТипУзлаXML.НачалоЭлемента Тогда
295+
296+ ИмяНовогоУзла = ЧтениеXML.ЛокальноеИмя;
297+ Лог.Отладка("Новый узел <%1>" , ИмяНовогоУзла);
298+ СоответствиеУзла = ПрочитатьXML (ЧтениеXML, ИмяНовогоУзла);
299+ ВставитьЭлементУзла(КорневойУзел, ИмяНовогоУзла, СоответствиеУзла);
300+
301+ ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Текст Тогда
302+
303+ ЗначениеСвойства = ЧтениеXML.Значение;
304+ Лог.Отладка("Прочитано значение " + ЗначениеСвойства);
305+ КорневойУзел.Вставить("_Значение" , ЗначениеСвойства);
306+
307+ ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.Комментарий Тогда
308+ ЗначениеСвойства = ЧтениеXML.Значение;
309+ Лог.Отладка("Прочитан комментарий " + ЗначениеСвойства);
310+ КорневойУзел.Вставить("_Комментарий" , ЗначениеСвойства);
311+
312+ ИначеЕсли ЧтениеXML.ТипУзла = ТипУзлаXML.СекцияCDATA Тогда
313+ ЗначениеСвойства = ЧтениеXML.Значение;
314+ Лог.Отладка("Прочитана СекцияCDATA " + ЗначениеСвойства);
315+ КорневойУзел.Вставить("_CDATA" , ЗначениеСвойства);
316+
317+ КонецЕсли ;
318+
319+ КонецЦикла ;
320+
321+ КонецПроцедуры
322+
323+ Процедура ВставитьЭлементУзла (КорневойУзел , Знач ИмяНовогоУзла , СоответствиеУзла )
324+
325+ ТипЭлементовУзла = ТипЗнч (КорневойУзел._Элементы);
326+ СоответствиеТекущегоЭлемента = Новый Соответствие();
327+ СоответствиеТекущегоЭлемента.Вставить(ИмяНовогоУзла, СоответствиеУзла);
328+
329+ Если ТипЭлементовУзла = Тип ("Массив" ) Тогда
330+ КорневойУзел._Элементы.Добавить(СоответствиеТекущегоЭлемента);
331+ ИначеЕсли ТипЭлементовУзла = Тип ("Соответствие" ) Тогда
332+
333+ УжеЕстьЗначение = НЕ КорневойУзел._Элементы[ИмяНовогоУзла] = Неопределено ;
334+
335+ Если УжеЕстьЗначение Тогда
336+ МассивЭлементов = Новый Массив;
337+
338+ Для каждого КлючЗначение Из КорневойУзел._Элементы Цикл
339+ ТекущийЭлемент = Новый Соответствие();
340+ ТекущийЭлемент.Вставить(КлючЗначение.Ключ, КлючЗначение.Значение);
341+ МассивЭлементов.Добавить(ТекущийЭлемент);
342+ КонецЦикла ;
343+
344+
345+ МассивЭлементов.Добавить(СоответствиеТекущегоЭлемента);
346+
347+ КорневойУзел._Элементы = МассивЭлементов;
348+
349+ Иначе
350+
351+ СоответствиеТекущегоЭлемента = Новый Соответствие();
352+ КорневойУзел._Элементы.Вставить(ИмяНовогоУзла, СоответствиеУзла);
353+
354+ КонецЕсли ;
355+ Иначе
356+
357+ ВызватьИсключение СтрШаблон ("Пришел не корректный тип значения <%1>" , ТипЭлементовУзла);
358+
359+ КонецЕсли ;
360+
361+ КонецПроцедуры
362+
363+ #КонецОбласти
0 commit comments