Я занимаюсь фронтенд-разработкой достаточно долго, чтобы заметить тенденцию с годами: молодые разработчики работают с новой парадигмой программирования, не понимая ее исторического контекста. Конечно, вполне понятно чего-то не знать. Интернет — это очень большое место с разнообразным набором навыков и специальностей, и мы не всегда знаем то, чего не знаем. Обучение в этой области — это постоянное путешествие, а не то, что происходит один раз и заканчивается. Показательный пример: кто-то из моей команды спросил, можно ли определить, уходят ли пользователи с определенной вкладки пользовательского интерфейса. Я указал на событие beforeunload в JavaScript. Но те, кто сталкивался с этим раньше, знают, что это возможно, поскольку они получали предупреждения о несохраненных данных на других сайтах, для которых типичным вариантом использования является beforeunload. Я также указал своему коллеге на события pageHide и VisibilityChange. Откуда я об этом узнал? Потому что он появился в другом проекте, а не потому, что я изучал его, когда впервые изучал JavaScript. Дело в том, что современные front-end фреймворки стоят на плечах технологических гигантов, которые им предшествовали. Они абстрагируют методы разработки, часто для лучшего опыта разработчиков, что уменьшает или даже устраняет необходимость знать или касаться того, что традиционно было важными концепциями интерфейса, которые, вероятно, должен знать каждый. Рассмотрим объектную модель CSS (CSSOM). Вы могли бы ожидать, что любой, кто работает с CSS и JavaScript, имеет большой практический опыт работы с CSSOM, но это не всегда так. Я работал над проектом React для сайта электронной коммерции, где нам нужно было загрузить таблицу стилей для выбранного в данный момент поставщика платежей. Проблема заключалась в том, что таблица стилей загружалась на каждой странице, хотя на самом деле она была нужна только на конкретной странице. Разработчик, которому было поручено реализовать это, никогда не загружал таблицу стилей динамически. Опять же, это совершенно понятно, если React абстрагирует традиционный подход, к которому вы, возможно, привыкли. CSSOM, вероятно, не то, что вам нужно в повседневной работе. Но вполне вероятно, что в какой-то момент вам придется с ним взаимодействовать, даже в разовом случае. Этот опыт вдохновил меня на написание этой статьи. Существует множество существующих веб-функций и технологий, к которым вы, возможно, никогда не прикоснетесь напрямую в своей повседневной работе. Возможно, вы новичок в веб-разработке и просто не знаете о них, потому что погружены в абстракцию конкретной среды, которая не требует от вас глубоких знаний или даже вообще. Я говорю конкретно об XML, который, как многие из нас знают, является древним языком, мало чем отличающимся от HTML. Я поднимаю этот вопрос из-за недавних дискуссий WHATWG, в которых предлагается удалить из браузеров значительную часть стека XML, известную как XSLT-программирование. Это именно та старая, существующая технология, которая у нас была в течение многих лет, и которую можно было бы использовать для чего-то столь же практичного, как ситуация с CSSOM, в которой оказалась моя команда. Работали ли вы раньше с XSLT? Давайте посмотрим, сможем ли мы в значительной степени опираться на эту старую технологию и использовать ее возможности вне контекста XML для решения сегодняшних реальных проблем. XPath: Центральный API Наиболее важной технологией XML, которая, возможно, является наиболее полезной за пределами прямой перспективы XML, является XPath, язык запросов, который позволяет вам найти любой узел или атрибут в дереве разметки с одним корневым элементом. Я испытываю личную привязанность к XSLT, но он также зависит от XPath, и личную привязанность следует отбросить при ранжировании. В аргументе за удаление XSLT не упоминается XPath, поэтому я полагаю, что это все еще разрешено. Это хорошо, поскольку XPath является центральным и наиболее важным API в этом наборе технологий, особенно когда вы пытаетесь найти что-то, что можно использовать помимо обычного использования XML. Это важно, поскольку, хотя селекторы CSS и можно использовать для поиска большинства элементов на вашей странице, они не могут найти их все. Более того, селекторы CSS нельзя использовать для поиска элемента по его текущей позиции в DOM. XPath может. Некоторые из вас, читающих это, возможно, знают XPath, а некоторые — нет. XPath — это довольно обширная область технологий, и я не могу научить вас всем основам, а также показать вам интересные вещи, которые можно с ней сделать, в одной статье, подобной этой. Я действительно пытался написать эту статью, но средняя публикация Smashing Magazine не превышает 5000 слов. Я был уже более чем2000 слов и только половина основ. Итак, я собираюсь начать делать интересные вещи с XPath и дам вам несколько ссылок, которые вы можете использовать для изучения основ, если вам это интересно. Объединение XPath и CSS XPath может делать множество вещей, которые не могут сделать селекторы CSS при запросе элементов. Но селекторы CSS также могут делать некоторые вещи, которые не может XPath, а именно, запрашивать элементы по имени класса.

CSS XPath .myClass /*[содержит(@class, "myClass")]

В этом примере CSS запрашивает элементы, содержащие имя класса .myClass. Между тем, пример XPath запрашивает элементы, содержащие класс атрибута, со строкой «myClass». Другими словами, он выбирает элементы с myClass в любом атрибуте, включая элементы с именем класса .myClass, а также элементы с «myClass» в строке, например .myClass2. XPath в этом смысле шире. Так что нет. Я не предлагаю отказаться от CSS и начать выбирать все элементы через XPath. Дело не в этом. Дело в том, что XPath может делать то, чего не может CSS, и может быть очень полезным, даже несмотря на то, что это старая технология в стеке браузера и может показаться неочевидной на первый взгляд. Давайте использовать обе технологии вместе не только потому, что мы можем, но и потому, что в процессе мы узнаем кое-что о XPath, сделав его еще одним инструментом в вашем наборе — о существовании которого вы, возможно, даже не подозревали! Проблема в том, что метод document.evaluate в JavaScript и различные методы селектора запросов, которые мы используем с CSS API для JavaScript, несовместимы. Я создал совместимый API запросов, чтобы мы могли начать, хотя, по общему признанию, я не особо задумывался об этом, поскольку это отклонение от того, что мы здесь делаем. Вот довольно простой рабочий пример многоразового конструктора запросов: См. Pen queryXPath [разветвленный] Брайана Расмуссена. Я добавил к объекту документа два метода: queryCSSSelectors (по сути это querySelectorAll) и queryXPaths. Оба они возвращают объект queryResults:

{ Тип запроса: узлы | строка | номер | логическое значение, результаты: Any[] // элементы HTML, элементы XML, строки, числа, логические значения, queryCSSSelectors: (запрос: строка, изменение: логическое значение) => queryResults, queryXpaths: (запрос: строка, изменение: логическое значение) => queryResults }

Функции queryCSSSelectors и queryXpaths запускают запрос, который вы им передаете, к элементам массива результатов, если, конечно, массив результатов имеет тип узлов. В противном случае он вернет queryResult с пустым массивом и типом узлов. Если для свойства amend установлено значение true, функции изменят свои собственные результаты запроса. Ни при каких обстоятельствах его нельзя использовать в производственной среде. Я делаю это исключительно для того, чтобы продемонстрировать различные эффекты совместного использования двух API запросов. Примеры запросов Я хочу показать несколько примеров различных запросов XPath, которые демонстрируют некоторые из их мощных возможностей и то, как их можно использовать вместо других подходов. Первый пример — //li/text(). Это запрашивает все элементы li и возвращает их текстовые узлы. Итак, если бы мы запросили следующий HTML: <ул>

  • один
  • два
  • три
  • … вот что возвращается:

    {"queryType": "xpathEvaluate", "results": ["один", "два", "три"], "resultType": "строка"}

    Другими словами, мы получаем следующий массив: ["один","два","три"]. Обычно для этого вы запрашиваете элементы li, превращаете результат этого запроса в массив, сопоставляете массив и возвращаете текстовый узел каждого элемента. Но мы можем сделать это более кратко с помощью XPath: document.queryXPaths("//li/text()").results.

    Обратите внимание: чтобы получить текстовый узел, нужно использовать text(), который выглядит как сигнатура функции — и так оно и есть. Он возвращает текстовый узел элемента. В нашем примере в разметке есть три элемента li, каждый из которых содержит текст («один», «два» и «три»). Давайте рассмотрим еще один пример запроса text(). Предположим, это наша разметка: Войти

    Давайте напишем запрос, который возвращает значение атрибута href: document.queryXPaths("//a[text() = 'Войти']/@href").results.

    Это запрос XPath к текущему документу, как и в прошлом примере, но на этот раз мы возвращаем атрибут href ссылки (элемента), содержащей текст «Войти». Фактический возвратрезультат: ["/login.html"]. Обзор функций XPath Существует ряд функций XPath, и вы, вероятно, с ними не знакомы. Я думаю, что есть несколько, о которых стоит знать, в том числе следующие:

    Begins-withЕсли текст начинается с определенного другого примера текста, Begins-with(@href, 'http:') возвращает true, если атрибут href начинается с http:. containsЕсли текст содержит конкретный другой пример текста, contains(text(), «Smashing Magazine») возвращает true, если текстовый узел содержит слова «Smashing Magazine» где угодно. countВозвращает количество совпадений с запросом. Например, count(//*[starts-with(@href, 'http:']) возвращает количество ссылок в узле контекста, содержащих элементы с атрибутом href, содержащим текст, начинающийся с http:. substringРаботает как подстрока JavaScript, за исключением того, что вы передаете строку в качестве аргумента. Например, substring("my text", 2, 4) возвращает "y t". substring-before Возвращает часть строки перед другой строкой. Например, substing-before("мой текст", " ") возвращает "мой". Аналогично, substring-before("hi","bye") возвращает пустую строку. substring-after Возвращает часть строки после другой строки. Например, substing-after("мой текст", " ") возвращает "текст". Аналогично, substring-after("hi","bye") возвращает пустую строку. нормализовать-пространство Возвращает строку аргумента с пробелами, нормализованными путем удаления начальных и конечных пробелов и замены последовательности символов пробелов одним пробелом. notВозвращает логическое значение true, если аргумент имеет значение false, в противном случае — false. true Возвращает логическое значение true. false Возвращает логическое значение false. concatТо же самое, что и concat в JavaScript, за исключением того, что вы не запускаете его как метод для строки. Вместо этого вы вводите все строки, которые хотите объединить. длина строкиЭто не то же самое, что длина строки в JavaScript, а скорее возвращает длину строки, переданной в качестве аргумента. TranslateThis принимает строку и заменяет второй аргумент на третий аргумент. Например, перевод("abcdef", "abc", "XYZ") выводит XYZdef.

    Помимо этих конкретных функций XPath, существует ряд других функций, которые работают точно так же, как их аналоги в JavaScript (или аналоги практически в любом языке программирования), которые вы, вероятно, также найдете полезными, например, пол, потолок, округление, сумма и т. д. Следующая демонстрация иллюстрирует каждую из этих функций: См. числовые функции Pen XPath [раздвоение] Брайана Расмуссена. Обратите внимание, что, как и большинство функций манипулирования строками, многие числовые функции принимают один вход. Это, конечно, потому, что они должны использоваться для запросов, как в последнем примере XPath: //li[floor(text()) > 250]/@val

    Если вы их используете, как это делается в большинстве примеров, вы в конечном итоге запустите его на первом узле, соответствующем пути. Есть также некоторые функции преобразования типов, которых вам, вероятно, следует избегать, поскольку в JavaScript уже есть свои проблемы с преобразованием типов. Но бывают случаи, когда вам нужно преобразовать строку в число, чтобы сравнить ее с каким-либо другим числом. Функции, которые устанавливают тип чего-либо, — это логические значения, числа, строки и узлы. Это важные типы данных XPath. И, как вы можете себе представить, большинство этих функций можно использовать с типами данных, которые не являются узлами DOM. Например, substring-after принимает строку, как мы уже рассмотрели, но это может быть строка из атрибута href. Это также может быть просто строка:

    const testSubstringAfter = document.queryXPaths("substring-after('hello world',' ')");

    Очевидно, что этот пример вернет нам массив результатов как ["world"]. Чтобы показать это в действии, я создал демонстрационную страницу, используя функции для объектов, которые не являются узлами DOM: См. Pen queryXPath [разветвленный] Брайана Расмуссена. Следует отметить удивительный аспект функции перевода: если у вас есть символ во втором аргументе (т. е. список символов, которые вы хотите перевести) и нет соответствующего символа для перевода, этот символ удаляется из вывода. Таким образом, это:

    Translation('Привет, меня зовут Иниго Монтойя, ты убил моего отца, приготовься умереть','abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,','*')

    …результат в виде строки, включая пробелы: [" * * ** "]

    Это означает, что буква «а» преобразуется в звездочку (*), но все остальные символы, не имеющие перевода в целевой строке, полностью удаляются. Пробелы — это все, что у нас осталосьмежду переведенными символами «а». Опять же, этот запрос:

    Translate('Привет, меня зовут Иниго Монтойя, ты убил моего отца, приготовься умереть','abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,','************************************************')")

    … не имеет проблемы и выводит результат, который выглядит следующим образом:

    "***** ** **** ** ***** ******* *** ****** ** ****** ******* ** ***"

    Вам может показаться, что в JavaScript нет простого способа сделать именно то, что делает функция перевода XPath, хотя во многих случаях с этим можно справиться replaceAll с помощью регулярных выражений. Вы можете использовать тот же подход, который я продемонстрировал, но это неоптимально, если все, что вам нужно, — это перевести строки. Следующая демонстрация оборачивает функцию перевода XPath для предоставления версии JavaScript: См. функцию перевода пером [разветвленную] Брайана Расмуссена. Где вы могли бы использовать что-то подобное? Рассмотрим шифрование Цезаря с трехзначным смещением (например, первоклассное шифрование 48 г. до н. э.):

    Translation("Цезарь планирует перейти Рубикон!", "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz", "XYZABCDEFGHIJKLMNOPQRSTUVWxyzabcdefghijklmnopqrstuvw")

    Входной текст «Цезарь планирует перейти Рубикон!» в результате получается «Zxbpxo fp mixkkfkd ql zolpp qeb Oryfzlk!» Чтобы дать еще один быстрый пример различных возможностей, я создал металлическую функцию, которая принимает строковый ввод и использует функцию перевода для возврата текста, включая все символы, принимающие умлауты. См. функцию Pen Metal [раздвоение] Брайана Расмуссена.

    const metal = (str) => { returntranslate(str, "AOUaou","ÄÖÜäöü"); }

    А если ввести текст «Motley Crue рулит, зажигай, чуваки!», возвращается «Mötley Crüe rüles, röck ön dudes!» Очевидно, что эту функцию можно использовать в самых разных пародиях. Если это вы, то эта статья TVTropes должна послужить вам источником вдохновения. Использование CSS с XPath Помните нашу главную причину использования селекторов CSS вместе с XPath: CSS в значительной степени понимает, что такое класс, тогда как лучшее, что вы можете сделать с XPath, — это сравнение строк атрибута класса. Это сработает в большинстве случаев. Но если бы вы когда-нибудь столкнулись с ситуацией, когда, скажем, кто-то создал классы с именами .primaryLinks и .primaryLinks2, а вы использовали XPath для получения класса .primaryLinks, то вы, скорее всего, столкнулись бы с проблемами. Если в этом нет ничего глупого, вы, вероятно, будете использовать XPath. Но мне грустно сообщать, что я работал в местах, где люди делают такие глупости. Вот еще одна демонстрация совместного использования CSS и XPath. Он показывает, что происходит, когда мы используем код для запуска XPath на узле контекста, который не является узлом документа. Посмотрите Pen css и xpath вместе [раздвоенные] Брайаном Расмуссеном. CSS-запрос — . linkedarticles a, который извлекает два элемента a в элементе div, которому присвоен класс . linkedarticles. После этого идут три «плохих» запроса, то есть запросы, которые не делают того, что мы от них хотим, при работе с этими элементами в качестве узла контекста. Я могу объяснить, почему они ведут себя не так, как вы могли бы ожидать. Три плохих запроса, о которых идет речь:

    //text(): возвращает весь текст в документе. //a/text(): возвращает весь текст внутри ссылок в документе. ./a/text(): не возвращает результатов.

    Причина таких результатов в том, что, хотя ваш контекст представляет собой элементы, возвращаемые из запроса CSS, // это противоречит всему документу. В этом сила XPath; CSS не может перейти от узла к предку, а затем к брату этого предка и спуститься к потомку этого брата или сестры. Но XPath может. Между тем, ./ запрашивает дочерние элементы текущего узла, где точка (.) представляет текущий узел, а косая черта (/) представляет переход к некоторому дочернему узлу — является ли это атрибутом, элементом или текстом, определяется следующей частью пути. Но у элемента, выбранного запросом CSS, нет дочернего элемента, поэтому этот запрос также ничего не возвращает. В последней демонстрации есть три хороших запроса:

    .//текст(), ./текст(), нормализовать-пространство(./text()).

    Запрос нормализации пространства демонстрирует использование функции XPath, а также устраняет проблему, включенную в другие запросы. HTML структурирован следующим образом:

    Автоматизация тестирования функций с помощью Selenium WebDriver

    Запрос возвращает перевод строки в начале и конце текстового узла.и нормализовать-пространство удаляет это. Использование любой функции XPath, которая возвращает что-то, кроме логического значения, с входным XPath, применимо и к другим функциям. В следующей демонстрации показано несколько примеров: См. примеры функций Pen xpath [разветвленные] Брайана Расмуссена. В первом примере показана проблема, на которую следует обратить внимание. В частности, следующий код:

    document.queryXPaths("substring-after(//a/@href,'https://')");

    … возвращает одну строку:

    "www.smashingmagazine.com/2018/04/feature-testing-selenium-webdriver/"

    Это имеет смысл, не так ли? Эти функции возвращают не массивы, а отдельные строки или отдельные числа. Запуск функции в любом месте с несколькими результатами возвращает только первый результат. Второй результат показывает, чего мы действительно хотим:

    document.queryCSSSelectors("a").queryXPaths("substring-after(./@href,'https://')");

    Возвращает массив из двух строк:

    ["www.smashingmagazine.com/2018/04/feature-testing-selenium-webdriver/","www.smashingmagazine.com/2022/11/automated-test-results-improve-accessibility/"]

    Функции XPath могут быть вложенными, как и функции в JavaScript. Итак, если мы знаем структуру URL-адреса Smashing Magazine, мы могли бы сделать следующее (рекомендуется использовать литералы шаблона): `перевести( подстрока( substring-after(./@href, 'www.smashingmagazine.com/') ,9), '/','')`

    Это становится слишком сложным до такой степени, что требуются комментарии, описывающие, что он делает: возьмите весь URL-адрес из атрибута href после www.smashingmagazine.com/, удалите первые девять символов, затем преобразуйте символ косой черты (/) в ничто, чтобы избавиться от конечной косой черты. Полученный массив:

    ["feature-testing-selenium-webdriver","automated-test-results-improve-accessibility"]

    Дополнительные случаи использования XPath XPath действительно может проявить себя в тестировании. Причину нетрудно понять: XPath можно использовать для получения каждого элемента в DOM из любой позиции в DOM, тогда как CSS — нет. Вы не можете рассчитывать на то, что классы CSS останутся согласованными во многих современных системах сборки, но с помощью XPath мы можем более точно сопоставлять текстовое содержимое элемента независимо от меняющейся структуры DOM. Было проведено исследование методов, позволяющих создавать отказоустойчивые тесты XPath. Нет ничего хуже, чем когда тесты выходят из строя и терпят неудачу только потому, что селектор CSS больше не работает, потому что что-то было переименовано или удалено. XPath также отлично справляется с извлечением нескольких локаторов. Существует несколько способов использования запросов XPath для сопоставления элемента. То же самое и с CSS. Но запросы XPath могут детализировать вещи более целенаправленно, что ограничивает возвращаемый результат и позволяет найти конкретное совпадение, где может быть несколько возможных совпадений. Например, мы можем использовать XPath для возврата определенного элемента h2, содержащегося внутри элемента div, который следует сразу за родственным элементом div, который, в свою очередь, содержит дочерний элемент изображения с атрибутом data-testID="leader": <дел> <дел>

    не понимаю этот заголовок

    <дел>

    Этот заголовок тоже не понятен

    <дел>

    Заголовок изображения лидера

    <дел>

    Это запрос: document.queryXPaths(` //дел[ следующий-родной брат::div[1] /img[@data-testID='лидер'] ] /ч2/ текст() `);

    Давайте запустим демо-версию, чтобы увидеть, как все это работает: См. запрос H2 Pen Complex [раздвоенный] Брайана Расмуссена. Так что да. Существует множество возможных путей к любому элементу теста с использованием XPath. Прекращение поддержки XSLT 1.0 Ранее я упоминал, что команда Chrome планирует удалить поддержку XSLT 1.0 из браузера. Это важно, поскольку XSLT 1.0 использует XML-ориентированное программирование для преобразования документов, которое, в свою очередь, опирается на XPath 1.0, который присутствует в большинстве браузеров. Когда это произойдет, мы потеряем ключевой компонент XPath. Но учитывая тот факт, что XPath действительно отлично подходит для написания тестов, я считаю маловероятным, что XPath в целом исчезнет в ближайшее время. Тем не менее, я заметил, что люди интересуются функцией, когда ее убирают. И это, безусловно, верно в случае, если XSLT 1.0 устарел. В Hacker News идет целая дискуссия, наполненная аргументами против прекращения поддержки. Сам пост является отличным примером создания платформы для ведения блога с помощью XSLT. ТыВы можете прочитать обсуждение самостоятельно, но речь идет о том, как JavaScript можно использовать в качестве прокладки для XLST для обработки подобных случаев. Я также видел предложения о том, что браузеры должны использовать SaxonJS, который является портом движков JavaScript Saxon XSLT, XQUERY и XPath. Это интересная идея, особенно учитывая, что Saxon-JS реализует текущую версию этих спецификаций, тогда как не существует браузера, реализующего какую-либо версию XPath или XSLT выше 1.0, и ни одного браузера, реализующего XQuery. Я обратился к Норму Тови-Уолшу из Saxonica, компании, стоящей за SaxonJS и другими версиями движка Saxon. Он сказал: «Если бы какой-либо поставщик браузеров был заинтересован в использовании SaxonJS в качестве отправной точки для интеграции современных технологий XML в браузер, мы были бы рады обсудить это с ними», — Норм Тови-Уолш.

    Но еще добавил: "Я был бы очень удивлен, если бы кто-нибудь подумал, что взять SaxonJS в его нынешнем виде и добавить его в сборку браузера без изменений было бы идеальным подходом. Поставщик браузера, в силу того факта, что он создает браузер, мог бы подойти к интеграции на гораздо более глубоком уровне, чем мы можем "извне"", - Норм Тови-Уолш.

    Стоит отметить, что комментарии Тови-Уолша прозвучали примерно за неделю до объявления об прекращении поддержки XSLT. Заключение Я мог бы продолжать и продолжать. Но я надеюсь, что это продемонстрировало возможности XPath и дало вам множество примеров, демонстрирующих, как использовать его для достижения великих целей. Это прекрасный пример старой технологии в стеке браузеров, которая до сих пор имеет множество полезных свойств, даже если вы никогда не знали о ее существовании или никогда не думали о ее использовании. Дальнейшее чтение

    «Повышение устойчивости автоматизированных веб-тестов с помощью естественного языка» (Цифровая библиотека ACM), Марун Айли, Юсеф Бакуни, Надер Джаллул и Рима Килани. В этой статье представлено множество примеров XPath для написания устойчивых тестов. XPath (MDN) Это отличное место для начала, если вам нужно техническое объяснение, подробно описывающее, как работает XPath. Учебное пособие по XPath (ZVON) Я считаю, что это учебное пособие является наиболее полезным в моем собственном обучении благодаря множеству примеров и четких объяснений. XPatherЭтот интерактивный инструмент позволяет работать непосредственно с кодом.

    You May Also Like

    Enjoyed This Article?

    Get weekly tips on growing your audience and monetizing your content — straight to your inbox.

    No spam. Join 138,000+ creators. Unsubscribe anytime.

    Create Your Free Bio Page

    Join 138,000+ creators on Seemless.

    Get Started Free