Как на странице сайта определить ссылку по фрагменту текста и без учёта регистра текста?

Имеется код со следующим сценарием:

  1. Поиск ссылок на странице
  2. Если текст содержит “программа на C#”, то код нажимает на ссылку.
private void button4_Click(object sender, EventArgs e)
        {
            List<IWebElement> Element = Browser.FindElements( By.CssSelector("#tabnews_newsc a") ).ToList();
 
            for (int i = 0; i < Element.Count; i++ )
            {
                String s = Element[i].Text;                
 
                if (s.Contains("программа на C#")) // если текст СОДЕРЖИТ
                {
                    Element[i].Click(); // КЛИК по новости, которая СОДЕРЖИТ искомый текст
                    break;
                }
            }
        }

ВОПРОС
Как сделать, чтобы поиск осуществлялся без учёта регистра текста для поиска?
Т.е. если текст содержит “программа на C#”, то переход осуществляется, а если текст содержит “Программа на C#” (слово “Программа” с большой буквы “П” ), то перехода по ссылке не происходит.

Перед сравнением текста переведите его в верхний или нижний регистр а потом сравнивайте с текстом соответствующим:

s.ToLower().Contains("программа на c#")

На счёт правильности кода не уверен. Но по идее должно работать)

P.S.: вообще проще через #xpath наверное вытаскивать только нужные элементы и уже кликать по ним

//h3//a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ', 'abcdefghijklmnopqrstuvwxyzабвгдеёжзиклмнопрстуфхцчшщьыъэюя'), 'программа на c#')]
2 лайка

При использовании предложенной вами строчки появляется ошибка.

ОШИБКА
‘string’ does not contain a definition for ‘contains’ and no extension method ‘contains’ accepting a first argument of type ‘string’ could be found (are you missing a using directive or an assembly reference?)

Скрин

ВОПРОС
Не могли бы вы подсказать как её исправить?

PS
Только осваиваю WebDriver Selenium заранее прошу извинить, если вопрос элементарный

Ошибку устранил.
Всё работает…

Вы бы не могли подсказать как сделать с помощью xpath на примере моего кода?

Пробовал вставить вашу строку, что-то не срабатывает.

//h3//a[contains(lower-case(.), "программа на c#")]

Не уверен на счет #xpath сделал его на основе вашего #css-selectors . Делаете поиск элементов по этому xpath. У вас будет в итоге список элементов которые только содержат такой текст, соответственно обходите этот список и кликаете по каждому элементу или что там у вас делает тест)

1 лайк

не могу нигде найти описание это части кода.
Что это такое?
В частности "lower-case(.)"

На java:

List<WebElement> elements = driver.findElements(By.cssSelector("#tabnews_newsc a"));
        for (WebElement ls : elements)
        {
            if (ls.getText().equalsIgnoreCase("программа на C#")) // если текст СОДЕРЖИТ
            {
                ls.click(); // КЛИК по новости, которая СОДЕРЖИТ искомый текст
            }
        }
1 лайк

By XPath:

List<WebElement> elements = driver.findElements(By.xpath("//a[contains(text(), 'программа на c#')]"));
1 лайк

Данный код будет выбирать текст, если слово "программа… " будет с большой буквы “П”, т.е. “Программа”?

PS
Всем спасибо за ответы

Да, будет собирать только ссылки, которые буквально содержат текст “программа на c#”
В принципе с помощью XPath можно задать любые критерии отбора.

1 лайк

Lower-case приводит текст к нижнему регистру. А точка это короткая запись text()

1 лайк

насколько хорошо xpath поддерживает кодировки ?

может проще сделать на с# - передать ignorecase несколькими способами оставить необходимые

 e = d.FindElements(By.CssSelector("#tabnews_newsc a"));
  String matcher = "(?i:" + "программа на c#" + ")";
 if (Regex.IsMatch(e.Text, matcher, RegexOptions.IgnoreCase)) {
 }
1 лайк

Так же добавлю, что lower-case это XPath 2.0 - который в данный момент не поддерживается браузерами.
А точка это не text(), а текущая нода относительно предиката…

2 лайка

Настолько хорошо, насколько их поддерживает веб-браузер.

В принципе, уже видно, что существует несколько путей решений задачи топикстартера. Лично мне вариант с прямым поиском по XPath видится самым производительным, так как сразу формируется массив из нужных элементов. В вашем же случае сперва сформируется массив из всех ссылок, а потом он еще должен перебираться, сравнивая каждый элемент с шаблоном регулярного выражения.

1 лайк

Ну в конкретном случае . будет равносильна использованию text(). В других случаях это будет текущая нода.
P.S.: вот страшный вариант для xpath 1.0:

//h3//a[contains(translate(., 'ABCDEFGHIJKLMNOPQRSTUVWXYZАБВГДЕЁЖЗИКЛМНОПРСТУФХЦЧШЩЬЫЪЭЮЯ', 'abcdefghijklmnopqrstuvwxyzабвгдеёжзиклмнопрстуфхцчшщьыъэюя'), 'программа на c#')]
1 лайк

Нет. Читайте спеку.

1 лайк

Я про то что оно работает.

1 лайк

А я про то, что вы утверждаете, что в данной конструкции

Что неверно:

1 лайк

Ясен пень оно будет работать по разному ) Я не утверждал что . == text(), я имел в виду что в некоторых случаях замена text() на . будет давать тот же результат. Мне так удобнее было записать пример и все. Главное что он работает.

1 лайк

Ну если для вас все ясно, расскажите топик-стартеру, что же просиходит к конструкции вида contains(.,'some text'), и чем оно отличается от contains(text(),'some text').

1 лайк