Разбор XML документа - почти все возможные способы

Публикация № 311011

Разработка - Практика программирования

XML DOM XPath

К вам пришел XML документ, как получить из него данные для обработки в 1С.
ЧтениеXML,  ДокументDOM, XPath, ФабрикаXDTO, ПакетыXDTO в сравнении.

 

При обмене данными, как бы он не производился  ( через файлы, через HTTP запросы или еще каким либо другим путем ) все равно основным форматом обмена является XML. В 1С существует несколько способов обработки XML  документов    какой из них выбрать по критерию логической простоты и быстродействия?  Для практической проверки различных методов был создан XML документ вида


 

Задачей всех проверяемых методов было получение из XML файла массива, состоящего из структур со свойствами Номер, Дата, Поставщик, Состав, причем свойство Состав само является массивом структур со свойствами Номенклатура и Количество.  

 

Первый метод – простое последовательное чтение XML.


 

Текущее положение в XML документе отслеживается в переменной  ТекущийПуть и при поступлении текстового узла на  основании этой переменной заполняются (или игнорируются) соответствующие данные 1С. Конечно, не совсем корректно оценивать логическую сложность программы в строках исходного текста, но тем не менее это самый большой объем  из всех методов  - 64 строки. Что касается быстродействия (оно проверялось на компьютере памятью в 8 Гб и процессором Intel i7 2.2 Ггц, было создано два файла один на 10 тысяч записей объемом 10 мегабайт, другой на 100 тысяч и 100 мегабайт соответственно) , то на файле 10 000 записей полная обработка заняла 30 секунд  и на файле в 100 мегабайт линейно увеличилась в 10 раз.

 

Второй метод – получение из XML файла документа DOM и последовательный перебор всех узлов полученного документа

 

 

Логически этот метод весьма незначительно проще прямого ЧтенияXML (57 строк кода против 62), а вот с быстродействие картина интересная: для файла в 10 тысяч записей быстродействие составило 12 секунд (быстрее более чем в два раза) ,  но для файла со 100 тысячами записей резко поднялась до 1000 секунд (медленнее более чем в три раза).

  

Третий метод подобен второму, но вместо последовательного перебора узлов применен отбор требуемых узлов в DOM документе  с помощью  выражений XPath .

 

Этот метод немного проще чем простой перебор узлов в DOM документе, но быстродействие … При 10 000 записей 69 секунд , а для 100 000 обработка длилась более часа, так и не завершилась, после чего была снята принудительно.

 

Очевидно метод с использованием DOM, в особенности при поиске узлов документа XPath выражениями, надо использовать только для небольших изменений DOM документа со сложной структурой узлов.

 

 

Все последующие методы используют для разбора XML документа фабрику XDTO.

 

Четвертый метод использует метод  ПрочитатьXML глобальной ФабрикиXDTO. При этом тип получаемого объекта не указывается, его определяет сам метод фабрики. Тут есть маленькая тонкость – в случае, если тип получаемого объектаXDTO не указан, фабрика не всегда может самостоятельно определить что она получила одиночный объект или список из нескольких одинаковых объектов ( в нашем примере если ПриходныйОрдер в XML документе будет один фабрика посчитает что ПриходыXDTO.ПриходныйОрдер это одиночный объект а не список).



 

Данный метод не только заметно проще, чем все предыдущие, но и показывает отличное быстродействие  на 10 000 записях 4,6 секунды, а при 100 000 обработка длится 46 секунд. Что показывает линейную зависимость от объема обрабатываемого файла.

 

Пятый метод схож с предыдущим, но глобальной фабрике XDTO подается на вход не только сам XML документ, но и его тип. Этот тип берется из ветки конфигурации XDTO-пакеты. (Если те кто передает вам XML данные хорошие люди, то они должны передать вам и XML схему данных – файл с расширением .xsd  из которого вы и создаете в своей конфигурации  XDTO-пакет – команда импорт XML схемы …, если нет требуемый пакет обычно не сложно создать вручную, анализируя переданные XML данные).

 

Один нюанс – частенько XML данные передают без указания URI пространства имен ( атрибут  xmlns). Если это так, то необходимо самому добавить недостающий атрибут в XML данные, что и делают первые три оператора процедуры.

 

Метод замечательный, как по простоте создания, так и по быстродействию – 3,1 секунды на 10 000 записях.

 

И последний метод. Это скорее некоторая модификация пятого метода, но для условия, что не используется объект конфигурации XDTO-пакет, и фабрика XDTO создается на ходу из текстового описания XML схемы. (Примечание 1-Конечно можно загнать схему в текстовый макет, и оттуда уже использовать, но для учебной программы так нагляднее. 2-Текстовый вариант XML схемы можно например  получить создав XDTO-пакет в любой конфигурации XDTO-пакет и  выполнив команду Экспорт XML схемы..)


В прилагаемой конфигурации все методы разбора XML представлены в общей команде РазобратьXML, там же в другой общей команде СоздатьXML представлены средства для создания тестовых данных.

Скачать файлы

Наименование Файл Версия Размер
РазборXML.cf

.cf 18,49Kb
05.11.14
706
.cf 18,49Kb 706 Скачать

Специальные предложения

Вознаграждение за ответ
Показать полностью
Комментарии
Избранное Подписка Сортировка: Дата
91. t_yuri 17 01.08.19 14:51 Сейчас в теме
Сорри, нашел ,в "Общие команды"...)
90. t_yuri 17 01.08.19 14:45 Сейчас в теме
(89)
Сорри, нашел все в "Общие команды"...)
89. t_yuri 17 01.08.19 13:42 Сейчас в теме
Почему в cf не все указанные варианты примеров?

В разборе вижу только:
// Простой обход дерева
// Использование XPath

Где другие варианты??
88. vlabal 27.02.19 15:39 Сейчас в теме
87. suepifanov 27.02.19 12:28 Сейчас в теме
(85) я просто проверял такие строки на тип Если ТипЗнч(ЗаявкаXDTO.POSBreakages.POSBreakage)=Тип("СписокXDTO") Тогда
Цикл... Иначе не цикл ...
85. vlabal 27.02.19 12:13 Сейчас в теме
Большое спасибо автору за примеры!
Возникла неудобная ситуация с обработкой списка в XML.
Если в списке одна строка, то возникает ошибка при попытке выполнить цикл, т.к. ЗаявкаXDTO.POSBreakages.POSBreakage является почему-то объектом XDTO, а если несколько строк, то ЗаявкаXDTO.POSBreakages.POSBreakage видится как СписокXDTO и обход проходит нормально, можно выкрутиться через попытку исключение, но красивое решение пока не удалось найти.

Для Каждого СтрокаPOSBreakages Из ЗаявкаXDTO.POSBreakages.POSBreakage Цикл

СтрокаPOSBreakagesСтруктура = Новый Структура("POSBreakage_ID,SC_POSBreakage_ID,POSBreakage_Name");
СтрокаPOSBreakagesСтруктура.POSBreakage_ID = СтрокаPOSBreakages.POSBreakage_ID;
СтрокаPOSBreakagesСтруктура.SC_POSBreakage_ID = СтрокаPOSBreakages.SC_POSBreakage_ID;
СтрокаPOSBreakagesСтруктура.POSBreakage_Name = СтрокаPOSBreakages.POSBreakage_Name;
ДокументЗаявкаСтруктура.POSBreakages.Добавить(СтрокаPOSBreakagesСтруктура);

КонецЦикла;

Предложите лучший вариант.
84. tovpeko 24.02.19 17:16 Сейчас в теме
Спасибо, познавательная статья, как раз в скором времени пригодится))
83. baakir 21 07.02.19 17:33 Сейчас в теме
(76)
.Последовательность().ПолучитьТекст(0)

Безмерно благодарен, уж как только не пробовал схемы XML загружать, ниче не получалось. Я бы тоже неделю искал если не больше, если бы не твой коммент.
82. stroga 83 28.11.18 13:45 Сейчас в теме
81. F1_1 31.10.18 13:06 Сейчас в теме
80. Andry.Boris 55 21.08.18 00:16 Сейчас в теме
Автору спасибо, пригодилось очень.
79. boss_kuz 89 18.08.18 04:27 Сейчас в теме
78. CatZero 16.08.18 08:34 Сейчас в теме
(77) В общие команды загляните
77. boss_kuz 89 04.08.18 06:15 Сейчас в теме
Почему в фале cf нет примеров кода использованного на картинках ? Лажа...
76. dimasts 22 02.04.18 16:35 Сейчас в теме
(75) Ответ на вопрос, может кому поможет (А Я УВЕРЕН В ЭТОМ ТАК КАК ПОТРАТИЛ НЕДЕЛЮ)

ОбъектXDTO.Body.DocumentObject_СписаниеСРасчетногоСчета[0].Контрагент.Последовательность().ПолучитьТекст(0)
Caliban; w_maG; baakir; KVG; eeeio; +5 Ответить 1
75. dimasts 22 02.04.18 09:40 Сейчас в теме
Не могу понять, как заставить фабрику прочитать значение из строки:
<Контрагент xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CatalogRef.Контрагенты">3722b978-d17a-11e5-89f0-001fc663b5b0</Контрагент>

Все объекты без проблем читаются методом = ФабрикаXDTO.ПрочитатьXML(ЧтениеXML)
и только контрагент имеет один атрибут type со значением CatalogRef.Контрагенты, куда девается ссылка?

Пакеты xdto вообще не использую, так как все объекты нормально читаются, но походу надо создать маленький пакет специально для этой строки.

Подскажите пожалуйста, как должен выглядеть этот микро-пакет или надо всё-таки создавать огромный пакет для всех объектов?
74. 🅵🅾️🆇 20.02.18 16:50 Сейчас в теме
(71) Ты серьезно?)
ТипЗнч(ФабрикаXDTO.СписокXDTO) = Тип("СписокXDTO")
73. 🅵🅾️🆇 20.02.18 16:01 Сейчас в теме
Возможно сочтете за некропостинг, но теперь многое из написаного можно записать еще более емко с помощью: ЗаполнитьЗначениеСвойств()

Вот упрощенный вариант понятного чтения в несколько строк небольших файлов, на примере типичного документа с табличной частью (сверка актов из 1с 77):
ЧтениеXML	= Новый ЧтениеXML;
ЧтениеXML.ОткрытьФайл(Файл.ПолноеИмя);
АктыXDTO	= ФабрикаXDTO.ПрочитатьXML(ЧтениеXML);
Акты		= Новый Структура("ОрганизацияИНН,ОрганизацияНаименование,КонтрагентИНН,КонтрагентНаименование,Договор,ОрганизацияФИО,ОрганизацияДолжность,КонтрагентФИО,КонтрагентДолжность,ДатаНачала,ДатаОкончания,Операции");
ЗаполнитьЗначенияСвойств(Акты, АктыXDTO);
Акты.Вставить("Операции", Новый Массив);
Для Каждого ОперацияXDTO Из АктыXDTO.Операция Цикл
	Операция	= Новый Структура("Номер,Операция,Дебет,Кредит,Согласован");
	ЗаполнитьЗначенияСвойств(Операция, ОперацияXDTO);
	Акты.Операции.Добавить(Операция);	
КонецЦикла; // Для Каждого Операция Из АктыXDTO.Операция
// Не забываем закрывать, господа:
ЧтениеXML.Закрыть();
Показать
mst; Vida; +2 Ответить
72. progaoff 01.02.18 14:46 Сейчас в теме
Подскажите, как правильно сделать XDTO пакет для xml файла,
Прикрепленные файлы:
71. EvgeniyNP 31.01.18 13:38 Сейчас в теме
(69) И еще вопрос.
можно ли в коде наложить условие на проверку, что это ОбъектXDTO или СписокXDTO?
70. EvgeniyNP 30.01.18 13:01 Сейчас в теме
(69)
и можно xmlns передавать из файла или нужно его задавать заранее?

я подразумевал, что нужно передевать в тип и можно ли взять это из файла?
69. EvgeniyNP 30.01.18 11:45 Сейчас в теме
А не подскажет кто-нибудь?
есть такой xml-файл


можно для него использовать 5 метод?
и можно xmlns передавать из файла или нужно его задавать заранее?
Прикрепленные файлы:
СчетФактураМФТИ.xml
68. Westbound 20.09.17 10:56 Сейчас в теме
(41) Получаешь последовательность, а потом текст:
Последовательность = ТвойОбъектXDTO_СТекстом.Последовательность();
Текст = Последовательность.ПолучитьТекст(0);
lelbraun; fmanaseev; +2 Ответить