XPath универсальный C# шаг работы с элементами

Karamzin

Client
Регистрация
24.05.2016
Сообщения
213
Благодарностей
432
Баллы
63
либо указывай название тэга. либо указывай доп. атрибуты тэга
 

Radzhab

Client
Регистрация
23.05.2014
Сообщения
1 500
Благодарностей
1 268
Баллы
113

Karamzin

Client
Регистрация
24.05.2016
Сообщения
213
Благодарностей
432
Баллы
63
Пардон. Забыл ссылку скинуть
http://lessons.zennolab.com/en/index
Если тебе именно по этому примеру, то так
(//h2[contains(text(), 'USA')]/preceding-sibling::input)[last()]
Но что-то мне подсказывает, что это лишь пример, а задача другая. В общем тут универсального решения нет. Надо смотреть на каждом сайте индивидуально. Эти чекбоксы везде по разному делают. Каждый извращается как может.


Здесь у тебя текст в h2, а кликать тебе надо по input, который находится рядом.
 

Radzhab

Client
Регистрация
23.05.2014
Сообщения
1 500
Благодарностей
1 268
Баллы
113
Если тебе именно по этому примеру, то так
(//h2[contains(text(), 'USA')]/preceding-sibling::input)[last()]
Но что-то мне подсказывает, что это лишь пример, а задача другая. В общем тут универсального решения нет. Надо смотреть на каждом сайте индивидуально. Эти чекбоксы везде по разному делают. Каждый извращается как может.


Здесь у тебя текст в h2, а кликать тебе надо по input, который находится рядом.
Проблема в том что я не хочу вручную по xpath искать этот радио Баттон и кликать на него. Я хочу задать keyword и чтобы система искала по этому ключевому слову сам элемент
 

Radzhab

Client
Регистрация
23.05.2014
Сообщения
1 500
Благодарностей
1 268
Баллы
113
Мне нужно универсальное решение
 

Karamzin

Client
Регистрация
24.05.2016
Сообщения
213
Благодарностей
432
Баллы
63

Radzhab

Client
Регистрация
23.05.2014
Сообщения
1 500
Благодарностей
1 268
Баллы
113

Radzhab

Client
Регистрация
23.05.2014
Сообщения
1 500
Благодарностей
1 268
Баллы
113
Код:
string key = "USA";
Tab tab = instance.ActiveTab;
tab.FindElementByXPath(string.format("(//h2[contains(text(), '{0}')]/preceding-sibling::input)[last()]", key), 0).RiseEvent("click", "Full");
Я же первый день на форуме чтобы что то элементарное просить)))
 

Karamzin

Client
Регистрация
24.05.2016
Сообщения
213
Благодарностей
432
Баллы
63
радио Баттон и кликать на него
ок. я тебя понял. Такого решения нет.
Как я сказал ранее вариантов этого радио баттона слишком много на разных сайтах. Где-то он выполнен в виде input, где-то button, где-то div с вложенным текстом, где-то div и снизу идентифицирующий span, а может h2, а может он сверху, а возможно текст на ступень выше элемента по которому надо кликать. И еще херова туча вариантов с множеством других тэгов и вариантов расположения (как я сказал, каждый сайт извращается по своему).
 
  • Спасибо
Реакции: Dimionix и Radzhab

z@jivalo

Client
Регистрация
27.12.2016
Сообщения
800
Благодарностей
179
Баллы
43
Radzhab может быть этот вариант //*[.='USA']
по xpath находит только тег h2 в котором и есть этот текст,
но дальше надо придумать что бы клик сработал.
 

backoff

Client
Регистрация
20.04.2015
Сообщения
6 095
Благодарностей
6 496
Баллы
113
как сделать мгновенный ввод текста?, чтоб не было эмуляции, а то когда текста много, тратиться очень много времени на ввод

юзаю такой код
Код:
//ввод текста
string xpath_exp = "//input[@aria-label='лалала']";
string action_ev = "set|value";
string set_action = project.Variables["text"].Value;
return CommonCode.FindElementAndExecuteAction(instance, xpath_exp, action_ev, set_action);
скинь готовый пример кода с эмуляцией - none
плиз, я не шарю в шарпе
 

webmasterfree

Client
Регистрация
03.02.2019
Сообщения
116
Благодарностей
17
Баллы
18
Данный код позволяет очень удобно работать с xpath из C# шага, задача кода - замена стандартных "кубиков" на более продвинутый метод поиска элементов - xpath, при этом в удобной обёртке.

Технология xpath очень гибкая, в частности одно из популярных применений (которые сложно сделать без неё стандартными средствами ZP) - поиск элементов методом "найти элемент, а в нём другой элемент, а в нём третий..." то есть вложенный поиск когда невозможно найти уникальный признак по которому можно сразу идентифицировать элемент.

Также можно например найти соседний элемент (который имеет уникальный признак), и от него "оттолкнуться" чтобы найти нужный нам элемент (который не имеет уникального признак поиска). В общем простор для поиска элементов просто широчайший.

Как работает:
- Вставляется функция в блок "общий код", это и есть обработчик
- Из C# шага вызывается код "клиента" который выполняет что вам надо (кликнуть, взять что-то, установить значение, в общем классический get|set|rise)

В чём основное удобство, вот так выглядит код в C# шаге:
C#:
string xpath_exp = "//select[@id='lang-chooser']/option[@selected='selected'][contains(.,'United States')]";
string action_ev = "rise|focus";
string set_action ="";

return CommonCode.FindElementAndExecuteAction(instance, xpath_exp, action_ev, set_action);
Входные параметры:
xpath_exp - выражение xpath для нахождения элемента
action_ev - что делаем с элементом, возможные варианты:

аргумент 1:
- get - взять значение
- set - установить значение
- rise - выполнить JS event

аргумент 2: то что делаем с элементом, например комплексные варианты с примерами:
get|width - взять ширину найденого элемента
set|value - установить значение в элемент, например в текстовое поле нужный вам текст
rise|click - клик по элементу

В общем здесь всё то же самое что и в конструкторе действий.

set_action - используется лишь в случаях когда делается set (например set|value или там set|style), то есть установка значения, в этом случае пишется указанный текст, то есть то что будет прописано в значении.

Также реализованы следующие фишки:
rise|scroll - промотает до нужного элемента
set|selecteditems - выбор выпадающего меню, при этом поддерживает Regex:ваш_текст

Прочая информация:
- Код работает начиная с версии ZP 5.8.0.0
- Используется тип эмуляции заданный в проекте (в настройках, либо заданный вами в шаге)
- Сейчас пока что нет возможности распознавать капчу таким образом (не сделан get|captcha)
- Если элемент не будет найден, то этот шаг выйдет с ошибкой
- Для составления xpath выражений удобно использовать расширение браузера FireFox под названием Firepath (ставится как дополнение к дополнению Firebug)
- Код написал darkdiver по моей просьбе, за что ему низкий поклон и большая благодарность
- Уроки по xpath можно найти здесь http://zvon.org/xxl/XPathTutorial/Output_rus/example1.html

Пример использования кода во вложениях.
Хоть и старая статья, но помогает до сих пор. Спасибо ребята. Выручили!
 
  • Спасибо
Реакции: nik-n и rediffusion

Porosenok

Client
Регистрация
26.09.2010
Сообщения
1 280
Благодарностей
96
Баллы
48
А как полученный innertext записать в список, чтобы построчно было? А то пишется по строчно, но берешь строку, а в итоге берется все содержимое
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 789
Благодарностей
5 721
Баллы
113

Porosenok

Client
Регистрация
26.09.2010
Сообщения
1 280
Благодарностей
96
Баллы
48
Ну оно записывает конечно. Но в итоге берешь строку - берется весь текст
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 789
Благодарностей
5 721
Баллы
113

Porosenok

Client
Регистрация
26.09.2010
Сообщения
1 280
Благодарностей
96
Баллы
48
C#:
var y = instance.ActiveTab.FindElementByXPath(".//*/select[contains(@id, '123')]", 0);
if (String.IsNullOrEmpty(y.GetAttribute("selecteditems")))
{

project.SendInfoToLog("Pusto");  
   
}
else {
IZennoList list = project.Lists["temp"];  
//List<string> list = new List<string>();
list.Add(y.GetAttribute("innertext"));
}
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 789
Благодарностей
5 721
Баллы
113
C#:
var y = instance.ActiveTab.FindElementByXPath(".//*/select[contains(@id, '123')]", 0);
if (String.IsNullOrEmpty(y.GetAttribute("selecteditems")))
{

project.SendInfoToLog("Pusto"); 
  
}
else {
IZennoList list = project.Lists["temp"]; 
//List<string> list = new List<string>();
list.Add(y.GetAttribute("innertext"));
}
не, как ИЗ списка берешь ?
 

Porosenok

Client
Регистрация
26.09.2010
Сообщения
1 280
Благодарностей
96
Баллы
48
кубиком получить строку
 

Phoenix78

Client
Read only
Регистрация
06.11.2018
Сообщения
11 789
Благодарностей
5 721
Баллы
113

Petr_G

Client
Регистрация
20.10.2017
Сообщения
96
Благодарностей
53
Баллы
18
@mig-z, воспользуйтесь этим снипетом:
C#:
Tab tab = instance.MainTab;
if (tab.IsBusy) tab.WaitDownloading();
// get document
Document doc = tab.MainDocument;

// find element by attribute
HtmlElementCollection heCol = doc.FindElementsByXPath(@"//a");

//вытаскиваем атрибут href из каждого элемента
var data = heCol.AttributesToString("href").Split(new string[] {Environment.NewLine},0).ToList();

//закидываем всё в список
project.Lists["Список 1"].AddRange(data);
project.SendInfoToLog("добавлено ["+data.Count+"] элементов");
Позже объединю это дело с кодом из первого поста.

Снипет ищет все совпадения по XPath (все теги <a>), вытаскивает у каждого совпадения свой аттрибут ("href"), и сохраняет их все в список ("Список 1").
Не объединили еще с основным кодом?
 

Astraport

Client
Регистрация
01.05.2015
Сообщения
4 991
Благодарностей
4 457
Баллы
113

Petr_G

Client
Регистрация
20.10.2017
Сообщения
96
Благодарностей
53
Баллы
18
Ещё годиков 5 подождите...
к чему непонятный сарказм! Я ничего не ждал, нашел через поиск и обратился к человеку с вопросом. И ваше мнение никто вроде не спрашивал!
 

Astraport

Client
Регистрация
01.05.2015
Сообщения
4 991
Благодарностей
4 457
Баллы
113
к чему непонятный сарказм! Я ничего не ждал, нашел через поиск и обратился к человеку с вопросом. И ваше мнение никто вроде не спрашивал!
Я и не тебе писал. Это форум, а не твоя личная переписка, не путай.
Ты спрашиваешь у чувака, который уже много лет не появляется на форуме.
 

Petr_G

Client
Регистрация
20.10.2017
Сообщения
96
Благодарностей
53
Баллы
18
Я и не тебе писал. Это форум, а не твоя личная переписка, не путай.
Ты спрашиваешь у чувака, который уже много лет не появляется на форуме.
можно же было так и написать, правильно? А не умничать.
 

TheBoss

Client
Регистрация
30.03.2015
Сообщения
529
Благодарностей
194
Баллы
43
Привет! А можете пожалуйста показать, как сделать условие, если найден элемент и если не найден?


string xpath_exp = @"//input[@id=""identifierId""]";
string action_ev = "set|value";
string set_action = project.Variables["test_var"].Value;
CommonCode.FindElementAndExecuteAction(instance, xpath_exp, action_ev, set_action);

Предположим в этом коде
 

IgorSush

Client
Регистрация
11.02.2016
Сообщения
312
Благодарностей
108
Баллы
43
Можно через try{} catch{}

C++:
    try{
        CommonCode.FindElementAndExecuteAction(instance, ".//a", "rise|click");
    }
    catch{
        throw new Exception("NOT FOUND");
    }

Можно и так:

C++:
El = CommonCode.FindElementAndExecuteAction(instance, XPath, "rise|click", "");
if(El == null){
    throw new Exception("Элемент не найден!");
}
 
  • Спасибо
Реакции: TheBoss

Кто просматривает тему: (Всего: 2, Пользователи: 0, Гости: 2)