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

Karamzin

Client
Joined
May 24, 2016
Messages
213
Reaction score
432
Points
63
либо указывай название тэга. либо указывай доп. атрибуты тэга
 

Radzhab

Client
Joined
May 23, 2014
Messages
1,500
Reaction score
1,269
Points
113

Karamzin

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


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

Radzhab

Client
Joined
May 23, 2014
Messages
1,500
Reaction score
1,269
Points
113
Если тебе именно по этому примеру, то так
(//h2[contains(text(), 'USA')]/preceding-sibling::input)[last()]
Но что-то мне подсказывает, что это лишь пример, а задача другая. В общем тут универсального решения нет. Надо смотреть на каждом сайте индивидуально. Эти чекбоксы везде по разному делают. Каждый извращается как может.


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

Radzhab

Client
Joined
May 23, 2014
Messages
1,500
Reaction score
1,269
Points
113
Мне нужно универсальное решение
 

Karamzin

Client
Joined
May 24, 2016
Messages
213
Reaction score
432
Points
63
Мне нужно универсальное решение
Code:
string key = "USA";
Tab tab = instance.ActiveTab;
tab.FindElementByXPath(string.format("(//h2[contains(text(), '{0}')]/preceding-sibling::input)[last()]", key), 0).RiseEvent("click", "Full");
 

Radzhab

Client
Joined
May 23, 2014
Messages
1,500
Reaction score
1,269
Points
113
Code:
string key = "USA";
Tab tab = instance.ActiveTab;
tab.FindElementByXPath(string.format("(//h2[contains(text(), '{0}')]/preceding-sibling::input)[last()]", key), 0).RiseEvent("click", "Full");
Мы не понимаем друг друга
 

Radzhab

Client
Joined
May 23, 2014
Messages
1,500
Reaction score
1,269
Points
113
Code:
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
Joined
May 24, 2016
Messages
213
Reaction score
432
Points
63
радио Баттон и кликать на него
ок. я тебя понял. Такого решения нет.
Как я сказал ранее вариантов этого радио баттона слишком много на разных сайтах. Где-то он выполнен в виде input, где-то button, где-то div с вложенным текстом, где-то div и снизу идентифицирующий span, а может h2, а может он сверху, а возможно текст на ступень выше элемента по которому надо кликать. И еще херова туча вариантов с множеством других тэгов и вариантов расположения (как я сказал, каждый сайт извращается по своему).
 

z@jivalo

Client
Joined
Dec 27, 2016
Messages
800
Reaction score
179
Points
43
Radzhab может быть этот вариант //*[.='USA']
по xpath находит только тег h2 в котором и есть этот текст,
но дальше надо придумать что бы клик сработал.
 

backoff

Client
Joined
Apr 20, 2015
Messages
6,225
Reaction score
6,556
Points
113
как сделать мгновенный ввод текста?, чтоб не было эмуляции, а то когда текста много, тратиться очень много времени на ввод

юзаю такой код
Code:
//ввод текста
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
Joined
Feb 3, 2019
Messages
116
Reaction score
17
Points
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

Пример использования кода во вложениях.
Хоть и старая статья, но помогает до сих пор. Спасибо ребята. Выручили!
 

Porosenok

Client
Joined
Sep 26, 2010
Messages
1,281
Reaction score
96
Points
48
А как полученный innertext записать в список, чтобы построчно было? А то пишется по строчно, но берешь строку, а в итоге берется все содержимое
 

Phoenix78

Client
Read only
Joined
Nov 6, 2018
Messages
11,789
Reaction score
5,729
Points
113
А как полученный innertext записать в список, чтобы построчно было? А то пишется по строчно, но берешь строку, а в итоге берется все содержимое
list.Add("строка");
 

Porosenok

Client
Joined
Sep 26, 2010
Messages
1,281
Reaction score
96
Points
48
Ну оно записывает конечно. Но в итоге берешь строку - берется весь текст
 

Phoenix78

Client
Read only
Joined
Nov 6, 2018
Messages
11,789
Reaction score
5,729
Points
113

Porosenok

Client
Joined
Sep 26, 2010
Messages
1,281
Reaction score
96
Points
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
Joined
Nov 6, 2018
Messages
11,789
Reaction score
5,729
Points
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
Joined
Sep 26, 2010
Messages
1,281
Reaction score
96
Points
48
кубиком получить строку
 

Phoenix78

Client
Read only
Joined
Nov 6, 2018
Messages
11,789
Reaction score
5,729
Points
113
кубиком получить строку
ну странно конечно, попробуй так получить table;
если и так неправильно брать будет, то наверно это баг.
 

Petr_G

Client
Joined
Oct 20, 2017
Messages
104
Reaction score
60
Points
28
@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
Joined
May 1, 2015
Messages
5,011
Reaction score
4,487
Points
113

Petr_G

Client
Joined
Oct 20, 2017
Messages
104
Reaction score
60
Points
28
Ещё годиков 5 подождите...
к чему непонятный сарказм! Я ничего не ждал, нашел через поиск и обратился к человеку с вопросом. И ваше мнение никто вроде не спрашивал!
 

Astraport

Client
Joined
May 1, 2015
Messages
5,011
Reaction score
4,487
Points
113
к чему непонятный сарказм! Я ничего не ждал, нашел через поиск и обратился к человеку с вопросом. И ваше мнение никто вроде не спрашивал!
Я и не тебе писал. Это форум, а не твоя личная переписка, не путай.
Ты спрашиваешь у чувака, который уже много лет не появляется на форуме.
 

Petr_G

Client
Joined
Oct 20, 2017
Messages
104
Reaction score
60
Points
28
Я и не тебе писал. Это форум, а не твоя личная переписка, не путай.
Ты спрашиваешь у чувака, который уже много лет не появляется на форуме.
можно же было так и написать, правильно? А не умничать.
 

TheBoss

Client
Joined
Mar 30, 2015
Messages
599
Reaction score
236
Points
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
Joined
Feb 11, 2016
Messages
312
Reaction score
108
Points
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("Элемент не найден!");
}
 
  • Thank you
Reactions: TheBoss

Users Who Are Viewing This Thread (Total: 1, Members: 0, Guests: 1)