Проверка равенства, неравенства, идентичности узлов в XPath

    С одной стороны, в языке XPath используются знакомые каждому программисту операторы сравнения «равно», «не равно», «меньше», «больше» и другие. С другой стороны, эти операторы умеют работать не только с примитивными типами, но и с целыми наборами узлов. Незнание правил сравнения наборов узлов может привести к некоторым сюрпризам.

    Попробуйте быстро ответить на вопрос, чему равно следующее выражение:

    foo = 'bar' and foo != 'bar'

    Если ваш ответ — false, автор предлагает читать дальше.

    Сравнение узла со строкой


    Простая задача: проверить, равен ли атрибут foo строке 'bar':

    @foo = 'bar'

    При решении обратной задачи довольно часто можно увидеть следующий код:

    @foo != 'bar'

    В большинстве случаев этот код работает так, как ожидается. Однако в случае, когда атрибут foo отсутствует, данное выражение возвращает false. Если внимательно прочесть документацию и перевести @foo != 'bar' на русский язык, получится следующее: существует хотя бы один атрибут foo, который не равен 'bar'. При отсутствии атрибута foo условие не выполняется, отсюда false.

    Правильное решение задачи:

    not(@foo = 'bar')

    Что в переводе на русский означает: не существует ни одного атрибута foo, равного 'bar'.

    Сравнение набора узлов со строкой


    Возьмём следующий документ:
    <list>
    <item>foo</item>
    <item>bar</item>
    <item>baz</item>
    </list>


    Применим различные сочетания операторов равенства, неравенства и отрицания:
    Выражение Перевод Результат
    item = 'foo' Есть хотя бы один элемент, равный 'foo'. true
    item != 'bar' Есть хотя бы один элемент, не равный 'bar'. true
    not(item = 'foo') Нет ни одного элемента, равного 'foo'. false
    not(item != 'baz') Все имеющиеся элементы равны 'baz'. false
    Как видите, возможна ситуация, когда выражение item = 'foo' and item != 'foo' возвращает true.

    Проверка идентичности узлов


    При сравнении двух узлов они приводятся к строке. Как быть, если нужно проверить не совпадение строкового представления, а идентичность? Другими словами, необходимо установить, что два проверяемых узла суть один и тот же узел. Такая задача, например, встречается в группировке Мюнха.

    Первое решение — на чистом XPath:

    count($foo | $bar) = 1

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

    Второе решение использует XSLT-функцию generate-id:

    generate-id($foo) = generate-id($bar)

    Данная функция по определению возвращает одинаковый результат для одного и того же узла. Если результаты работы функции равны, значит, исходные узлы идентичны.

    Комментарии и дополнения приветствуются.
    Share post

    Comments 52

      0
      по долгу службы пришлось разбираться с xpath/xquery
      можете посоветовать материалы для чтения в открытом доступе? а то я больше пары простеньких туториалов не нашел
        +2
        Кроме документации могу посоветовать XSLT в примерах.
          0
          не, xslt не интересует. интересует xquery
          • UFO just landed and posted this here
              0
              мне для работы с xml базой данных :) xslt тут не при чем :)
              • UFO just landed and posted this here
                  0
                  спасибо!
                  0
                  Лучшее руководство по XPath, которое я видел, именно в книге «Технология XSLT» Валикова. Ее правда сейчас очень трудно найти в бумажно виде. Но тот, кто ищет, всегда найдет :)
                    0
                    Хорошая книга, часто выручала.
                    Но, исключительно, как справочник, изучать по ней — категорически бы не советовал.
            +1
              0
              на самом деле очень хороший сайт, есть почти всё. Разобраться во всём можно
                +1
                Странно — почему заминусовали вас? www.w3schools.com/XPath/xpath_syntax.asp — например вполне себе минимум нормальный по Xpath селекторам.
                0
                Советую прочитать относящиеся к XPath статьи из www.dpawson.co.uk/xsl/sect2/sect21.html

                Ну и тут уже посоветовали книжку Валикова.
                  +1
                  Могу посоветовать старый добрый www.zvon.org
                  Есть и статьи и туториалы и даже утилиты-тесты, чтоб можно было поиграться с xpath и визуально видеть какие узлы попали в выборку. Главы посвящённые xpath есть так же и в туториалах по xslt (кстати русская версия на www.raleigh.ru, упомянутая razetdinov как раз и есть перевод с этого сайта).
                  +1
                  Я бы ещё добавил, что особенности сравнения в XPath позволяют делать некоторые вещи намого проще, чем в других языках.
                  Например join: person[@name = $vip/person/@name] позволяет найти людей, у которых имя встречается в списке VIP (а не равно всему списку сразу, как кажется).
                    0
                    Offtopic.

                    Скажите, а на Ваш взгляд XSLT — красив, элегантен? От него получаешь удовольствие?
                      +2
                      Есть много задач, которые достаточно быстро и красиво. Особенно когда много работы с XML.
                        +1
                        На мой взгляд, язык хорошо справляется со своей задачей: трансформацией XML-документов.
                        Имеет место многословность синтаксиса, но при соблюдении определённых правил почти не мешает.
                          +3
                          Да. Большое удовольствие.
                          Плюс я использую XSLT как шаблонизатор во всех своих проектах.
                            0
                            Спасибо. А то я его совсем не знаю, немного полистал-почитал как-то документацию — и что-то таким громоздким показался… Но у меня уже 3 голоса «за», надо на досуге посмотреть еще раз.
                              +1
                              Громоздкость компенсируется, если используешь IDE с автодополнением кода. В таком случае особой разницы не заметно.

                              Плюс можно парой строчек с XML такие чудеса вытворять, о которых раньше и подумать страшно было.
                                0
                                Спасибо за ответ!
                            +1
                            XSLT — лучшее, что можно придумать для presentation layer
                            0
                            Дополнение по generate-id($foo) = generate-id($bar): если под сравнение попадёт множество $foo, где первым узлом будет $bar — выражение вернёт true.
                            То же самое будет если обе переменные будут множествами и первыми узлами в обоих будет один и тот же узел.
                              0
                              Жаль, что XSLT среди Российских веб-разработчиков, так не популярен. Гораздо проще забыв про валидность html и полное отделение логики от представления делать сайты на псевдо-шаблонизаторах.
                              Освоил создание сайтов на XML+XSLT в 2002г, с тех пор не признаю других связок, но студии с которыми приходится работать, считают это слишком сложной и трудоемкой технологией, и что сайты на ней нельзя делать. Если кто поскажет правильный довод, чтобы переубедить, буду благодарен.
                              Свои личные проекты создаю только на XSLT с трансформацией на стороне сервера.
                                0
                                > Если кто поскажет правильный довод, чтобы переубедить, буду благодарен.

                                «Так делает Яндекс».

                                Беда у XSLT одна — скорость.
                                И что-то поделать с этой бедой затруднительно.
                                Радости XPath и DOM дорого стоят.
                                  0
                                  Вы противоречите сами себе — если бы скорость трансформации была насколько узким местом, то Яндекс вряд ли бы ее использовал для подавляющего большинства своих сервисов.
                                    0
                                    Я нигде не говорил, что скорость «настолько узкое место, что XSLT нельзя использовать».
                                    Практически всегда скоростью можно пожертвовать в угоду достоинств.
                                      0
                                      Ай, отправил не дописав.

                                      Однако, XSLT всегда будет медленнее любого простого шаблонизатора.
                                        0
                                        Я вам следующее скажу… Для XSL трансформаций, так же как и для работы с самим деревом используются, в основном, библиотеки написанные преимущественно на Си. А это означает что скорость отработки «pure» скриптового шаблонизатора (как вы сказали «простого») будет, как минимум, сопоставима с XSLT. Однако, подход XML + XSLT обладает такими вкусностями, что никаким иным шаблонизаторам и не снилось.
                                          0
                                          Они не могут быть сопоставимы, как раз из-за «вкусностей».
                                          Накладные расходы сильно больше. В том числе, по памяти.

                                          Работа с деревом тяжёлая.
                                          Много тяжелей, чем разобрать строку шаблона по REGEX'у и дёрнуть вызовы инструкций.

                                          Лучше, конечно, иметь какой-нибудь пример и посмотреть на цифры, но у меня такого примера, к сожалению, нет.
                                            0
                                            Даже если бы и был. Сравнивать, по многим причинам, не уместно.

                                            >Много тяжелей, чем разобрать строку шаблона по REGEX'у и дёрнуть вызовы инструкций.
                                            Для таких целей, конечно, и нет смысла заморачивать с XSLT. Он предназначен для задач большего масштаба.
                                      +1
                                      Успешно использую XSLT в проекте с посещаемостью ~7.000.000 хитов в день. Все работает на одном выделенном сервере с парой ксеонов. Так что проблемы скорости XSLT во многом надуманы
                                        0
                                        Рибяты, я не говорю, что XSLT — жуткий тормоз.
                                        Несколько лет делал сайты только с его применением, скорость достаточна.

                                        Но, в сравнении с простыми шаблонизаторами, где примитивные возможности и такой же синтаксис, XSLT, понятное дело, проигрывает.

                                        Бывает (бывает), что на серьёзных шаблонах и объёмных страницах время трансформации — 3/4 всего времени генерации. Что, конечно, существенно.
                                          –1
                                          >>Но, в сравнении с простыми шаблонизаторами, где примитивные возможности и такой же синтаксис, XSLT, понятное дело, проигрывает.

                                          у XSLT примитивные возможноcти?

                                          Я не встречал ниодного шаблонизатора круче XSLT :) особенно если есть внутренние протоколы в системе.
                                            +1
                                            Запятую после «синтаксис» видите?..
                                            Понимаете, что там заканчивается часть, относящаяся к «простым шаблонизаторам»?
                                              –1
                                              Учи русский.

                                              Построение твоей фразы:

                                              даже простые шаблонизаторы, с примитивными возможностями и таким же синтаксисом выигрывают у XSLT
                                                0
                                                Прочтите комментарий целиком. Имеется в виду проигрыш в скорости, а не в наборе возможностей.
                                                  0
                                                  Я его целиком и прочел. Построение фразы — в ней сравниваются шаблонизаторы с примитивными возможностями, которые «понятное дело» дело, выигрывают у XSLT в скорости — заставляет неподготовленного читателя сделать вывод что XSLT — медлен и примитивен.
                                                  0
                                                  > Учи русский.

                                                  Всего хорошего.
                                                    0
                                                    за «ты» извиняюсь не специально, как то быстро писал.
                                                    но от остального не отказываюсь.
                                        0
                                        А в чём бонус по сравнению с шаблонизатором?
                                        Мне кажется с XSLT кода гораздо больше, HTML сложнее предсказать по коду, etc.
                                          0
                                          Может быть и неудачный пример но:
                                          Допустим есть большой проект, программная часть отдает только XML данные, есть верстальщик который знает только XSLT,
                                          перед ним лежит распечатка развернутого дерева данных всего проекта, всех модулей, всех блоков.
                                          Ему все видно и понятно.
                                          А допустим, если используются шаблоны аля smarty, верстальщику придется спрашивать прогера как называются те или иные элементы и как к ним добраться, думаю с другими шаблонами-скриптами будет тоже самое.
                                          Про объемность кода, забываешь когда понимаешь удобство Xpath. Да и просто уметь быстро набирать код.
                                            0
                                            Верстальшик который знает именно XSLT это очень особая ситуация.

                                            У нас например в 90% случаев как раз программисты знают вёрстку.
                                            Потому что это несложно и полезно знать.

                                            Да и просто уметь быстро набирать код.

                                            Программирование — искусство читаемости, а не скорости набора.
                                              0
                                              We Are Typists First, Programmers Second
                                              Согласен с Джефом: скорость набора имеет значение.
                                                0
                                                Это про другое — я имею в виду, что при выборе технологии важнее не сколько писать, а насколько хорошо читается. Скорость печати при этом важна, но не относится непосредственно к вопросу выбора.
                                                0
                                                >программисты знают вёрстку… потому что это несложно и полезно знать.
                                                Баги верстки, внесенные подобными знатоками самые тяжелые для выявления.
                                                Впрочем, Smarty-верстальщик «разбирающийся» в программировании тоже способен на многое.
                                                Да и вообще XSLT тем и хорош, что разрешает 99% конфликтов программист-верстальщик.
                                                  0
                                                  > Баги верстки, внесенные подобными знатоками самые тяжелые для выявления.
                                                  Пример?
                                                    0
                                                    Последний в моей практике — внесение невалидного кода приводило к нарушениям работы в JS.
                                                    Да в общем какая разница? Каждый должен заниматься своим делом.
                                                      0
                                                      Это удивительно, но мои программисты и правда знают верстку, и даже знают JS (до уровня prototypes/closures).

                                                      A human being should be able to change a diaper, plan an invasion, butcher a hog, conn a ship, design a building, write a sonnet, balance accounts, build a wall, set a bone, comfort the dying, take orders, give orders, cooperate, act alone, solve equations, analyze a new problem, pitch manure, program a computer, cook a tasty meal, fight efficiently, die gallantly. Specialization is for insects.


                                                      Но исходный вопрос был даже не про это — верстальщик который знает XSLT, но не способен разобраться с другими языками темплейтов — немного странно звучит для меня.
                                                        0
                                                        >мои программисты и правда знают верстку
                                                        Главное чтобы не верстали :)
                                                        «Беда, коль пироги начнет печи сапожник, а сапоги тачать пирожник.» (с) И.А. Крылов

                                                        >верстальщик который знает XSLT, но не способен
                                                        Могут быть проблемы не когнитивного плана, а физиологического. Например может мешать рвотный рефлекс. Мне например очень трудно подавить его при виде Smarty, хотя он не самый отвратительный.
                                                        0
                                                        Jquery — например падает если обращается к таблицы у которой есть namespace :)

                                          Only users with full accounts can post comments. Log in, please.