Find only links that are followed by outcomes - selenium

Referencing this page, I'm trying to get all of the n Markets > links but ONLY those that are followed by odds. You may have to scroll through a few pages to see an example on the site or there is a screenshot posted below.
From the screenshot, the links that I want (circled in green) are followed by odds (circled in red). I do NOT want the links (marked with a red X) that are not followed by odds (circled in yellow).
Is it possible to get all the .purple-arrow elements based on if .bettype:nth-child(1) .bet-party exists beside it?
Should be simple enough with following and preceding yet this is not giving desired.
//*[contains(#href,'/sports-betting/soccer/')]/ancestor::*[contains(#class,'bet-party')]/preceding-sibling::span['other-matches']//*[contains(#href, '/sports-betting/soccer/')]

You can do this with XPath.
//div[#class='container-fluid'][not(.//div[contains(#class,'no-outcomes')])]//a[#class='purple-arrow']
Breaking it down
//div[#class='container-fluid']
Find a DIV that contains the class 'container-fluid'. These are the top level containers that hold the entire row of HTML for each match.
[not(.//div[contains(#class,'no-outcomes')])]
It must not have a descendant DIV that contains the class 'no-outcomes'. If the DIV has this class, that row has no odds posted so we don't want these.
//a[#class='purple-arrow']
and finally... return the link with the class 'purple-arrow'.
You can test this in Chrome dev tools using $x().

Related

Selenium find element next to another one

I need to find an element that is located next to another one depending to an if condition.
For example, I'm trying to retrieve the bottom with the word “Log In & Pay” only if I found the words ‘DANA’ before.
I can find the first element with text DANA in this way, but how can I find then the next botton element with the text “Log In & Pay” ?
driver.findElement(By.xpath ("//*[contains(text(), 'DANA')]"));
Below the Html page:
Get the span with the desired text, find the closest ancestor div which contains both els, find the el you want from there. i.e.
//span[contains(text(), 'DANA')]
//ancestor::div[#class='web-pay-wallet-inside-wrap']
//div[#class='action']
/div[contains(text()='Log In & Pay')]
try using nested predicates
//div[span[contains(text(), 'DANA')]]/following-sibling::div[#class='action']/div
Explanation
//div[span[contains(text(), 'DANA')]] finds the div which contains span with text DANA
following-sibling::div finds the following div at the same level
Selenium 4 introduces relative locators which allow to look up elements in relative position to others. Like:
above
below
right of
left of
and even "near"
You can find examples here.

xpath on the site is constantly changing

Peace. I registered a test on the amazon site. Doing a search of 11 iphone and then coming to a page of full products i choose first but its xpath
// span [contains (text (), 'Apple iPhone 11 (64GB) - Black')]
The problem is that I can use this xpath but tomorrow the xpath will be renamed because the first product is changed for example:
// span [contains (text (), 'Apple iPhone 11 Pro (64GB) - Space Gray')]
But I always choose the first product among all iphones even when the product changes?
Thanks.
This is the page
https://www.amazon.co.uk/s?k=iphone+11&crid=3GCCCW0Q2Z1MQ&sprefix=iph%2Caps%2C220&ref=nb_sb_noss_2
Use index and following xpath to get the first element.
(//a[#class='a-link-normal a-text-normal']/span)[1]
Always try to find something on the page that is very unlikely to change. If the element that you're looking for doesn't have such properties, look at it's ancestors.
For example, in this case, you can see that one of this span's ancestors have cel_widget_id="MAIN-SEARCH_RESULTS" which'll most likely remain constant. So, the following xpath:
//span[#cel_widget_id="MAIN-SEARCH_RESULTS"]//h2/a/span
will give you all such titles. You can get the first index as
(//span[#cel_widget_id="MAIN-SEARCH_RESULTS"]//h2/a/span)[1]
You could use the class of the search item span:
//span[#class="a-size-medium a-color-base a-text-normal"]
Then if you can do:
first_iphone = driver.find_element_by_xpath('//span[#class="a-size-medium a-color-base a-text-normal"]')
Although all search items are all the same class, (in this case a-size-medium a-color-base a-text-normal) the find_element_by_xpath method will only look for the first one.

How to move to sibling in selenium

I have this code in html. and I want to go to a sibling node.
I search by title (since this is a unique value in the UI), but I want to move to the same level but with different class name that will contains ant-select-tree-switcher_close.
This is the xpath to what is marked, and I just want to move in the same level for the first span, but without span1, or any hard coded solution. I want to search by class name that contains the words ant-select-tree-switcher_close as some text in the class name.
the xpath is:
//*[#title='Arts/Ent'] this is marked in yellow
I want to go to the purple section regards
You can use preceding-sibling
//*[#title='Arts/Ent']/preceding-sibling::*[contains(#class, 'ant-select-tree-switcher_close')]
If you want to use the 'Arts/Ent' WebElement to locate the sibling you can use
./preceding-sibling::*[contains(#class, 'a')]

Concise Xpath to simulate finding an element regardless of page structure? (selenium)

If you're visually looking at a webpage and there is something clickable and unique on the page, you'll just click it. Without thinking about the page structure.
I'm interested to see what the most concise xpath is that could be constructed to simulate this in a versatile manner.
For example, target the "I'm feeling Lucky" button on the Google homepage:
//*[contains(#*, 'Lucky')]
The above works. But would fail in the element contained Lucky as inner text, or if the wrong case was specified. As such, our xpath needs to cater for any sensitivity and also look for the given string matching inner-text as well.
How could the above xpath be expressed in the most concise yet encompassing structure?
There is nothing thats very generic and executing such xpaths could be costly also at times.
"//*[contains(#*, 'Lucky')] | //*[contains(text(), 'Lucky')]"
Above is one xpath you can combine to get some results. You start specifying which nodes you don't to examine or ones which you want to examine
"//*[contains(#*, 'Lucky')] | //*[contains(text(), 'Lucky')][not(self::script|self::td)]"
And you can keep improving it
It's not possible to create a versatile XPath to accurately/reliability locate an element by text.
Why?
Because the text evaluated by an XPath is not necessary rendered in the page.
Because there's a hight chance to end-up with multiple matches since each ancestor also contains the expected text.
But mainly because there's too many rules/specific cases to consider.
But if I had to create one, then I'd start with this one:
"(html/body//*[not(self::script or self::style)][contains(concat(#value, normalize-space()), 'MyText')])[last()]"
Get all the descendants of the <body>
html/body//*
except <script> and <style>
[not(self::script or self::style)]
where the value attribute or normalize html contains 'MyText'
[contains(concat(#value, normalize-space()), 'MyText')]
then returns the last and deepest match
[last()]

XSL / XSL-FO: Different formatting of a block depending on its page position on PDF page

I'm new in this mailing list, so please apologize any of my wrongdoings.
FOP 1.1
Question: Is there any condition to find the position of a text-block in on PDF page.
This is the problem:
I need to change the formatting of a title-block depending on its position on the page.
If the title-block appears somewhere in the (vertical) middle of the page, I want to add a line on top of it.
if the title-block appears at the beginning/top of a page the line must not appear
Does XSL-FO have a way to do that?
From http://lists.w3.org/Archives/Public/www-xsl-fo/2015Sep/0002.html:
I used a white background on the
fo:region-before and a negative margin on the title to 'push' the
'border-before' of the title under the fo:region-before.
This requires that the FO processor supports negative values of
'margin-top', which is allowed but not required (http://www.w3.org/TR/xsl11/#margin-top). It also requires
that the FO processor will 'paint' the fo:region-before after painting
the fo:region-body.