https://infostart.ru/public/311011/
http://scientes.tmweb.ru/32/?commentId=47
Читать XML файл в лоб часто не удобно. Чтобы было удобнее обрабатывать данные XML можно воспользоваться Xpath.
Правда есть один недостаток: быстродействие... Этот метод хорош для небольших файлов со сложной структурой.
Для примера рассмотрим файл XML:
<?xml version="1.0" encoding="UTF-8"?>
<Данные>
<Объекты>
<Объект Имя="УчасткиГазопроводов">
<Параметры>
<Параметр ИмяПараметра="ВГ_КодУчастка" Наименование="В г код участка" ТипЗначения="Строка(50)"/>
<Параметр ИмяПараметра="ГлубинаПрокладки" Наименование="Глубина прокладки, м" ТипЗначения="Число(10.2)"/>
<Параметр ИмяПараметра="ГлубинаПрокладкиМаксимум" Наименование="Глубина прокладки максимум" ТипЗначения="Число(10.2)"/>
<Параметр ИмяПараметра="ГлубинаПрокладкиМинимум" Наименование="Глубина прокладки, м" ТипЗначения="Число(10.2)"/>
<Параметр Имя="ГрунтКоррозионнаяАгрессивность" Наименование="Коррозионная агрессивность грунта" ТипЗначения="Ссылка.ВыдыКоррозионнойАгрессивностиГрунта"/>
<Параметр Имя="ГрунтМетодЗащитыОтКоррозии" Наименование="Грунт метод защиты от коррозии" ТипЗначения="Ссылка.МетодыЗащитыОтКоррозии"/>
</Параметры>
</Объект>
</Объекты>
<ЗначенияСсылочныхТипов>
<Ссылка.ВыдыКоррозионнойАгрессивностиГрунта Иерархический="false">
<Значения>
<ЗначениеПараметра Значение="высокая" Родитель="" ЭтоГруппа="false"/>
<ЗначениеПараметра Значение="низкая" Родитель="" ЭтоГруппа="false"/>
<ЗначениеПараметра Значение="средняя" Родитель="" ЭтоГруппа="false"/>
</Значения>
</Ссылка.ВыдыКоррозионнойАгрессивностиГрунта>
<Ссылка.МетодыЗащитыОтКоррозии Иерархический="true">
<Значения>
<ЗначениеПараметра Значение="пассивная" Родитель="" ЭтоГруппа="true"/>
<ЗначениеПараметра Значение="электрохимическая" Родитель="" ЭтоГруппа="true"/>
<ЗначениеПараметра Значение="не требуется" Родитель="" ЭтоГруппа="false"/>
<ЗначениеПараметра Значение="Электрохимическая" Родитель="" ЭтоГруппа="false"/>
<ЗначениеПараметра Значение="дренажная" Родитель="электрохимическая" ЭтоГруппа="false"/>
<ЗначениеПараметра Значение="катодная" Родитель="электрохимическая" ЭтоГруппа="false"/>
<ЗначениеПараметра Значение="протекторная" Родитель="электрохимическая" ЭтоГруппа="false"/>
<ЗначениеПараметра Значение="весьма усиленная изоляция" Родитель="пассивная" ЭтоГруппа="false"/>
<ЗначениеПараметра Значение="лакокрасочное покрытие" Родитель="пассивная" ЭтоГруппа="false"/>
<ЗначениеПараметра Значение="экструдированный полиэтилен" Родитель="пассивная" ЭтоГруппа="false"/>
</Значения>
</Ссылка.МетодыЗащитыОтКоррозии>
</ЗначенияСсылочныхТипов>
</Данные>
Надо получить перечень "Объекты" и его "Параметры", а потом перечень "ЗначенияСсылочныхТипов". Получать данные будем с помощью запросов:
- "/Данные/Объекты/Объект" - чтобы получить список объектов.
- "/Данные/ЗначенияСсылочныхТипов" - чтобы получить значения ссылочных типов
Пример кода:
ДОМ=новый ПостроительDOM;
ЧтениеXML=Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(ИмяФайлаXML);
ДокументДОМ=ДОМ.Прочитать(ЧтениеXML);
РазыменовательПИ=ДокументДОМ.СоздатьРазыменовательПИ(ДокументДОМ);
ЗапросXML="/Данные/Объекты/Объект";
Путь=ДокументДОМ.СоздатьВыражениеXPath(ЗапросXML,РазыменовательПИ);
РезультатВыборки = Путь.Вычислить(ДокументДОМ);
ЧтениеXML.Закрыть();
ВыборкаОбъект=РезультатВыборки.ПолучитьСледующий();
Пока ВыборкаОбъект<>неопределено Цикл
...
ВыборкаОбъект=РезультатВыборки.ПолучитьСледующий();
КонецЦикла;
В переменную ВыборкаОбъект помещается значение типа ЭлементDOM.
Получить имя узла: ВыборкаОбъект.ИмяУзла (в нашем примере "Объект")
Получит значение атрибута по имени: ИмяПараметра= ВыборкаОбъект.Атрибуты.ПолучитьИменованныйЭлемент("ИмяПараметра").ТекстовоеСодержимое;
Перебрать коллекцию дочерних узлов: Для каждого ДочернийУзел ИЗ ВыборкаОбъект.ДочерниеУзлы Цикл ... КонецЦикла;
Получить значение булево значение атрибута: ЭтоГруппа = XMLЗначение(Тип("Булево"), ЗначениеПараметра.Атрибуты.ПолучитьИменованныйЭлемент("ЭтоГруппа").ТекстовоеСодержимое);
Пока не обнулили значение ДокументДОМ, можно выполнять различные запросы к загруженному документу XML.
Чтобы была такая возможность и не писать каждый раз повторяющийся код, текст кода был разбит на 2 процедуры.
Первое обращение:
&НаСервере
Функция ПолучитьВыборкуПоЗапросуXpath(Знач ДокументДОМ, Знач ЗапросXML, Знач РазыменовательПИ)
Перем Путь;
Путь=ДокументДОМ.СоздатьВыражениеXPath(ЗапросXML,РазыменовательПИ);
Возврат Путь.Вычислить(ДокументДОМ);
КонецФункции
Процедура...
РезультатВыборки = Неопределено;
ДокументДОМ = Неопределено;
РазыменовательПИ = Неопределено;
ЗапросXML="/Данные/Объекты/Объект";
СформироватьРезультатВыборкиXML(ИмяФайлаПараметров, ЗапросXML, РезультатВыборки, ДокументДОМ, РазыменовательПИ);
ВыборкаОбъект=РезультатВыборки.ПолучитьСледующий();
Пока ВыборкаОбъект<>неопределено Цикл
...
ВыборкаОбъект=РезультатВыборки.ПолучитьСледующий();
КонецЦикла;
Второе обращение
ЗапросXML = "/Данные/ЗначенияСсылочныхТипов";
РезультатВыборки = ПолучитьВыборкуПоЗапросуXpath(ДокументДОМ, ЗапросXML, РазыменовательПИ);
ВыборкаЗначения=РезультатВыборки.ПолучитьСледующий();
ДокументДОМ, РазыменовательПИ сохраняем, чтобы была возможность неоднократно обращаться к загруженному XML документу.
Если верить статье в первой ссылке, то методы использующие DOM работают очень медленно. Более быстрый способ - использовать ФабрикаXDTO.
Есть и минус - проблемы с определением списка. Список - это последовательность элементов одного с одинаковым именем элементов. Если в списке всего один элемент, то ФабрикаXDTO посчитает его свойством, поэтому требуется делать проверку. Обращаться к атрибутам можно через точку, как к свойствам объекта.
Пример на том же файле XML:
ЧтениеXML=Новый ЧтениеXML ;
ЧтениеXML.ОткрытьФайл(ИмяФайлаПараметров);
ДанныеXML = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
Если ТипЗнч(ДанныеXML.Объекты.Объект) <> Тип("СписокXDTO") Тогда
СписокОбъектовВДГО = Новый Массив();
СписокОбъектовВДГО = СписокОбъектовВДГО.Добавить(ДанныеXML.Объекты.Объект);
Иначе
СписокОбъектовВДГО = ДанныеXML.Объекты.Объект;
КонецЕсли;
Для каждого ОбъектВДГО из СписокОбъектовВДГО Цикл
ИмяОбъектаВДГО = ОбъектВДГО.Имя;
...
КонецЦикла;
Если ТипЗнч(ДанныеXML.ЗначенияСсылочныхТипов.СсылочныйТип) <> Тип("СписокXDTO") Тогда
СписокСсылочныхТипов = Новый Массив();
СписокСсылочныхТипов.Добавить(ДанныеXML.ЗначенияСсылочныхТипов.СсылочныйТип);
Иначе
СписокСсылочныхТипов = ДанныеXML.ЗначенияСсылочныхТипов.СсылочныйТип;
КонецЕсли;
Для каждого СсылочныйТип из СписокСсылочныхТипов Цикл
...
КонецЦикла;
|