Xpath без учета регистра в Chrome или Firefox

Я прочитал ответы на эти три вопроса о поиске XPath без учета регистра:

нечувствительный к регистру xpath contains () возможно?

Использование верхнего и нижнего регистра функции xpath в selenium IDE

XPath находит текст в любом текстовом узле

Когда я пробую решения XPath 1 и 2, предложенные там в Chrome и Firefox, ни один из них не работает (хорошо).

Я ищу слово, которое в настоящее время написано в верхнем регистре, а остальные в нижнем регистре (например, Example), но translate(.,'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLOMNOPQRSTUVWXYZ') вообще не может найти строку при использовании хотя бы двух букв. Я пробовал EX (2 совпадения, ни одного из них в примере), ex (0 совпадений), Ex (0), xa (0), XAM (0)

Изменение порядка перевода на translate(.,'ABCDEFGHIJKLOMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz') приводит к EX (0 совпадений), ex (0), Ex (0), xamp (1 попадание - правильно !! Но я должен исключить начальную букву, что недопустимо) , ха (0)

Попытка решений XPath 2.0, предложенных в ответах, указанных выше, возвращает следующие ошибки:

XPath 2.0

Я хочу выполнить поиск этого XPath без учета регистра

//div[@class='nav group']//a[contains(text(), 'Example')]

Как мне это сделать?


person d-b    schedule 08.06.2019    source источник
comment
Я не на 100% уверен, что понимаю ваш вопрос. Если вы хотите найти точное совпадение регистра, не используйте перевод. Если вы хотите найти слово НЕЗАВИСИМО от регистра, которое вы подразумеваете, принудительно используйте весь текст либо в верхнем, либо в нижнем регистре, затем сравните результат с таким же текстом - ПРИМЕР или пример, а не Пример.   -  person Bill Hileman    schedule 10.06.2019


Ответы (3)


К сожалению, спустя 12 лет после публикации XPath 2.0, несмотря на все известные ограничения XPath 1.0, производители браузеров до сих пор не обновили свои реализации XPath.

Доступны сторонние реализации (например, Saxon-JS поддерживает XPath 3.1), так что это один из возможных путей продвижения вперед.

Но пока вы используете только английский алфавит, обходной путь XPath 1.0 с использованием

contains(translate(., 'abcde...', 'ABCDE...'), "EXAMPLE")

должно работать нормально.

Вы можете либо перевести все в верхний регистр и проверить соответствие поисковому запросу в верхнем регистре, либо перевести все в нижний регистр и проверить соответствие поисковому запросу в нижнем регистре.

person Michael Kay    schedule 08.06.2019
comment
Не работает. $x("//div[@class='nav group']//a[contains(translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'), 'Example')]") ничего не соответствует. Зачем нужен начальный ., ? - person d-b; 08.06.2019
comment
Прочтите, что я написал. Если вы переведете его в верхний регистр, он будет содержать EXAMPLE, а не Example. С использованием . а не text () - предпочтительный способ получить строковое значение элемента контекста. - person Michael Kay; 08.06.2019

Вот xpath.

//div[@class='nav group']//*[translate(.,'ABCDEFGHIJKLMNOPQRSTUVWXYZ','abcdefghijklmnopqrstuvwxyz')='example']

Chrome:  введите описание изображения здесь Консоль:  введите описание изображения здесь

person supputuri    schedule 08.06.2019
comment
Вы поменяли мой a на span, который сломал его. Это было специально? В любом случае, используя //div[@class='nav group']//a[translate('Example','abcdefghijklmnopqrstuvwxyz','ABCDEFGHIJKLMNOPQRSTUVWXYZ')], я получаю 54 хита там, где я должен получить один. Он соответствует всем остальным элементам в списке, в котором находится Example. Есть идеи, почему? Мой исходный XPath соответствует только интересующему меня элементу. - person d-b; 08.06.2019
comment
Не могли бы вы проверить мой обновленный ответ. Я как раз проверял диапазон ... - person supputuri; 09.06.2019
comment
Это единственный вариант, который у меня работает во всех остальных ответах StackOverflow. - person Tim Yao; 04.05.2021

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

public String translate(String text) {
    return "translate(text(),'" + text.toUpperCase() + 
           "','" + text.toLowerCase() + "')='" + text.toLowerCase() + "'";
}

public String translateNormalized(String text) {
    return "translate(normalize-space(text()),'" + text.toUpperCase() + 
           "','" + text.toLowerCase() + "')='" + text.toLowerCase() + "'";
}

Я использую эти функции для создания локатора xpath, а именно:

String xpath = "//a[" + translateNormalized("Click here for more info") + "]";
person Bill Hileman    schedule 10.06.2019
comment
Как использовать эти функции в службе, которая ожидает XPath в качестве входных данных? - person d-b; 10.06.2019
comment
Во-первых, их может потребоваться изменить, чтобы использовать содержит вместо равно, я предполагаю, что вы знаете, как это сделать. Как и в примере, который я привожу в конце, после изменения метода на contains вы должны назначить строку "//div[@class='nav group']//a[" + translate("Example") + "]" и передать ее как локатор xpath. - person Bill Hileman; 10.06.2019
comment
Но опять же, если вы ищете ТОЧНОЕ совпадение в случае с примером, вам вообще не следует использовать перевод, потому что он будет игнорировать регистр и возвращать все экземпляры примера независимо от регистра. - person Bill Hileman; 10.06.2019