Язык XPath в 1С.
Если кому-то интересно, то попробую поделиться тем, как я использую методы языка XPath в той части, в которой этот язык удалось "внедрить" в 1С.
Основным стимулом, побудившим меня заинтересоваться методами этого парсера (XPath), был достаточно большой размер файлов XML и их значимое регулярное количество. Для справки, файлы от 5 до 10 мБайт в количестве, несколько десятков за сутки. Кто-то из "маэстро бигдаты" может посмеяться над такими размерами и объемами, но мне, как говорится, "для счастья - хватило".
Основным содержимым этих файлов были так всеми нами любимые коды маркировки. А возникающие вопросы выглядели примерно так - "отобрать все серии продукции, где код маркировки от позиции N до позиции NN равен строке 'ABСDE.....' ". При этом должны проверяться файлы, созданные с даты "X" по дату "Y". То есть сотни мегабайт XML.
Сразу натолкнулся на статью //infostart.ru/1c/articles/415439/
Прочел.... Потом еще много чего находил и читал. Со временем приобрел какой-то опыт, которым и поделюсь.
Итак, "XPath" вещь вполне полезная, а безальтернативность (применительно к 1С) автоматически делает ее самой лучшей. Если есть коллеги, которые еще не пользовались этим механизмом, то для лучшего понимания, определю XPath как "язык запросов для текстов XML". По-моему, вполне похожее определение. Ведь если взять любую таблицу и начать ее построчно читать, сравнивая поля таблицы с какими-то значениями для поиска необходимого, то в примитивной работе с файлами XML приходится делать то же самое. Открывать текст XML в объекте и пробегаться "по узелкам". Но однажды таблицы баз данных стали огромными, и кто-то придумал язык SQL. Видимо, парсер XPath придумали по аналогичной причине.
А еще, можно по тексту XML создать ДокументDOM, и там тоже есть несколько методов поиска. Но эти методы даже примерно не создают возможностей парсера. И уж если дело дошло до создания ДокументаDOM, то уже надо вовсю использовать парсер XPath, который и "вшит" в объект ДокументDOM, как отдельный раздел методов.
Сам язык xPath я не нашел в документации 1С. Но описаний синтаксиса этого языка и описаний его функций вполне достаточно на самых разных сайтах. Это нетрудно найти и сразу начать пользоваться. А вот специфические "мульки" этого языка в платформе 1С я уже проверил на себе. Чем и делюсь, итак.
1. Метод объекта ДокументаDOM, с которого начинается поиск (парсинг) выглядит так
"ВычислитьВыражениеXPath(<Выражение>, <УзелКонтекста>, <Разыменователь>, <ТипРезультата>)",
Где
<Выражение> - это текстовая строка, написанная по стандартам парсера и создющая ось (оси) поиска;
<УзелКонтекста> - стартовая позиция поиска (является элементом, узлом DOM) ;
<Разыменователь> - возможно, специфический объект 1С (я не так уж плотно изучал XPath вне платформы 1С и не могу сказать, есть ли такой объект в этом парсере у других платформ);
<ТипРезультата> - системное перечисление, указывающее на то, в виде чего надо получить результат поиска.
Первый параметр метода можно заполнить только в тот момент, когда появится понимание того, как парсер строит оси поиска. Не могу сказать, что у меня это понимание возникло за 5 сек., но и назвать этот интеллектуальный напряг - подвигом, тоже не приходится. Вполне поддающаяся осмыслению и пониманию логическая конструкция.
Второй параметр не нуждается в описании. Даже если не знать желаемый стартовый узел, то всегда можно написать <ДокументDOM.ЭлементДокумента> и вести поиск от корневого (основного) элемента документа.
А вот третий параметр потребовал много времени на понимание. Это объект <РазыменовательПространствИменDOM >. Что он делает? Вроде бы, все просто, он "пространства разыменовывает". Вернее, должен был бы разыменовывать. Но делает он это весьма своеобразно, я бы даже сказал, капризно. Активно пользуясь парсером XPath, я до сих пор считаю, что именно странное поведение объекта Разыменователь является самой большой заковыркой в парсере для платформы 1С.
Как я понимаю суть разыменования пространств. Это нивелирование (очистка) префиксов имен элементов и атрибутов текста XML.
То есть, привести способ записи имен элементов и атрибутов к режиму простой (неквалифицированной) записи. При наличии элементов, например "skl:Номенклатура", "zvd:Номенклатура" и "mgz:Номенклатура" разыменователь аннулирует их квалифицированные имена (условно сотрет префиксы), после чего все эти элементы будут рассматриваться при парсинге (формированию осей поисков) исключительно по своим простым (безпрефиксным) именам. Хотелось бы, чтобы это было так. На деле, после многодневных мучений выяснилось, что Разыменователь в 1С добросовестно разыменовывает те пространства, которые в платформе 1С числятся "своими или родными". Я иначе это понимание не могу сформулировать. Нельзя сказать, что указаный объект не работает, он безусловно работает, но по какому то заданному набору пространств, как я убедился методом "тыка". Попытка заставить его разыменовывать какие-то иные имена пространств приводит к несложной ситуации. Ошибок нет, разыменования тоже нет! Поэтому! При составлении строки поиска, по которой формируется ось (оси) поиска обязательно пользуйтесь только квалифицированными именами элементов. А вот в отношении атрибутов разыменователь работает в полном объеме! Такой вот казус) Это означает, что если вам нужны элементы с именем "Номенклатура", но такие имена у вас есть в двух и более пространствах (с разными префиксами), вам придется указывать их - все и строка поиска будет выглядеть, например, так: "/skl:Номенклатура|zvd:Номенклатура|mgz:Номенклатура".
Игнорировать объект Разыменователя (параметр как NULL) в методе поиска тоже нельзя, так что придется его создавать перед поиском в любом случае, даже осознавая его бесполезность. Конструктор этого объекта позволяет создать разыменователь для конкретного пространства (набора пространств) имен. Я пользуюсь самым простым вариантом. Я использую вариант конструктора, где можно указать УзелDOM и объект при конструировании сам узнает - какие пространства есть в конкретном заданном узле. И я указываю весь документ DOM, вот так <Новый РазыменовательПространствИменDOM(ДокументDOM)>. При таком раскладе разыменователь вроде бы должен "обезфамилить" все имена всех пространств в документе, но такого счастья у меня еще ни разу не получилось. Так что, еще раз напомню, в строке поиска все имена элементов - только квалифицированные! При соблюдении этого условия парсер работает "на ура", отбирает элементы, атрибуты или их содержимое по любым, самым замысловатым условиям отбора, инструментария в синтаксисе и функциях языка xPath вполне хватает.
Теперь о получаемом результате. Из особенностей использования результата поиска отмечу такой момент. Результат поиска не сериализируется, надо "перебирать вручную".
Вот системное перечисление <ТипРезультатаDOMXPath >. Два его значения, а именно <НеупорядоченныйИтераторУзлов > и <УпорядоченныйИтераторУзлов > предлагают коллекцию найденных значений. Поэтому первым действием будет позиционирование на первый элемент коллекции
РезультатПоиска.ПолучитьСледующий();
//И только затем вход в цикл
Пока РезультатПоиска <> Неопределено Цикл
//...... строки команд по обработке результата;
РезультатПоиска.ПолучитьСледующий();
КонецЦикла;
На этом, кажется, все. В остальном надо только совершенствовать понимание принципов и закономерностей формирования строк поиска.
Я активно использую этот парсер вместе с тем методом, который я описывал в своей предыдущей статье. Мне приходилось иметь дело с достаточно сложными конструкциями XML. Если ставить задачу создания, например, пакета XDTO сразу для всего получаемого текста XML, то такой объект получается крайне громоздким, сложным в описании, а главное, бессмысленным, т.к в очень многих случаях из всей этой сложной конструкции, содержащей десятки и сотни элементов, нам из них реально нужны пара-тройка. И вот тут парсер незаменим! Я получаю требуемые мне элементы с помощью парсера, моментально собираю легкую конструкцию СхемыXML, применительно именно к тем элементам, которые я нашел и по такой схеме создаю Фабрику, которая позволяет мне работать уже с полноценным объектом, с заданными типами и .д.
В этой связи я чуть иначе смотрю на споры, что лучше XML или JSON. Вроде того, что последний - меньше по размеру. А я могу спросить, а зачем работать со всем файлом сразу? Отберите только нужное из большого XML и спокойно работайте с этим мизером....