Xpath select items except last item wth contain syntax - html

I want to select the following html items (action,comedy) but except the last one (tags).
To select all my follow code is working:
//*[#id="video-tags"]//a[contains(#href,'tags')]
But to select except the last one (tags), it won't work with my follow code:
//*[#id="video-tags"]//a[contains(#href,'tags') not(position() > last() -1)]
The html
<ul id="video-tags">
<li>Uploader: </li>
<li class="profile_name">wilco</li>
<li><em>Tagged: </em></li>
<li>action, </li>
<li>comedy, </li>
<li>more <strong>tags</strong></li>
</ul>
Thanks in advance
Nick

Aside from the syntax error - you need an and, i.e. contains(#href,'tags') and not(position()...) - you're tripping up on a subtlety of how // is defined.
The XPath //a[position() < last()] will not give you every a except the last one, it will give you every a that is not the last a inside its respective parent element. Since each li contains at most one a, every a is the last a in its respective parent, so this test will match nothing at all.
You can achieve what you want by wrapping most of the expression in parentheses and putting the position check in a separate predicate
(//*[#id="video-tags"]//a[contains(#href,'tags')])[position() < last()]
The parentheses cause the final predicate to apply to the node set selected by the expression as a whole, rather than just to the a location step, i.e. it will first find all the a elements whose href contains "tags", then return all but the last of these selected elements in document order.
Technical explanation - the definition of // in XPath is that it is a shorthand for /descendant-or-self::node()/ (including the slashes), which is a location step that gives you this node and all its descendant nodes. So //a means /descendant-or-self::node()/child::a, and //a[something] means /descendant-or-self::node()/child::a[something] - the predicate applies to the child:: step, not the descendant-or-self:: one. If you want to apply a predicate to the descendant search then you should use the descendant:: axis explicitly - /descendant::a[something].

try this
(//ul[#id="video-tags"]//a[contains(#href,'tags')]/text())

Related

select only and element on a list of xpaths

$x("//div[#class='card-info__container']/div[3]/a")
using this I've found the container, but now I can't get the specific element I need.
when I enter this the response is:
⯆(3) [a.cta.btn, a.cta.btn, a.cta.btn]
⯈0: a.cta.btn
⯈1: a.cta.btn
⯈2: a.cta.btn
how can I take only the first one?
You can use the at() method to select the first item from the array of a that is returned from executing the XPath:
$x("//div[#class='card-info__container']/div[3]/a").at(0)
For an XPath that returns a list of elements,
xpath
you can select only the first element via indexing:
(xpath)[1]

Filtering name with two condition

I have a sample list of student and grades/subject in this file
enter image description here
https://docs.google.com/spreadsheets/d/1NeHlUaRnbvdJ2yJ38fUETGgBoYseQ8CuXmwRCwObAlM/edit#gid=0
On the range A16:A I'd like to see the list of names who has the grades of around 90-100 when I check any of the checkbox on B15:k15
the first example is when I check all of the boxes
I will only see the first name on the list because he is the only one with the 90-100 scores on all subject
2nd example when I check B15 and C15
I will only see the 1st and 2nd names on the list because he's those who only able to get a 90-100 score on those two subjects.
Is there a way to do this kind of filtering? thank you so much
Since this is your first post, I'm going to go with the approach I think you'll find easiest to understand. It's a long formula (which I've placed in a new sheet called "Erik Help" in A16), but it's just a repeat of the same element several times:
=FILTER(A2:K11, IF(B15=TRUE, B2:B11>=90, B2:B11^0), IF(C15=TRUE, C2:C11>=90, B2:B11^0), IF(D15=TRUE, D2:D11>=90, D2:D11^0), IF(E15=TRUE, E2:E11>=90, E2:E11^0), IF(F15=TRUE, F2:F11>=90, F2:F11^0), IF(G15=TRUE, G2:G11>=90, G2:G11^0), IF(H15=TRUE, H2:H11>=90, H2:H11^0), IF(I15=TRUE, I2:I11>=90, I2:I11^0), IF(J15=TRUE, J2:J11>=90, J2:J11^0), IF(K15=TRUE, K2:K11>=90, K2:K11^0))
The first argument of FILTER tells the function what to filter (in this case A2:K11).
After that, an IF statement is set up to check each checkbox. If the checkbox is checked, the FILTER will only include students who obtained a 90 or higher in that subject.
If the checkbox is NOT checked, then the student is automatically included (that's the part that says "B2:B11^0" etc., since anything to the zero-power equals 1, and 1 and TRUE are the same to Google Sheets). In other words, if no checkboxes were checked, then all students would read TRUE for all subjects, i.e., all students would be included (or, to think of it another way, no one is rules out). While the ^0 is not strictly necessary (i.e., any number other than zero is the same as TRUE), I think it's better formula practice and easier for others to understand if TRUE is represented either as TRUE or as 1.
I also set conditional formatting on A15:A, to bold the name as you had it. (The conditional formatting rule says, in English, "If anything is there, use bold.") You can see the rule by clicking anywhere in the range A15:A, then selecting Format > Conditional formatting from the menu and clicking the open the rule that appears in the window to the right of the screen.

VBA - IE Nest selection item with ID

Trying to select the Export button below which has an ID and name. I know I can getelementbyID but not sure how to then specify to further drill into the getattribute("name") because the getelementbyID wil only return 1 value, not an array
Thanks!
#Mturks83
getElementsByName("export")(0) the first part will give you the array of elements called export the (0) gives you the first.
It is faster to use querySelector than getElementsBy.
For example, just got direct with an attribute = value selector
ie.document.querySelector("[name=export]")
If more than one then add the parent td element id
ie.document.querySelector("#bottomButtonRow [name=export]")
Reading:
css selectors

how to use both (and) and (or) in xpath

I am trying to create an xpath with using (and) and (or) both expression together but not getting success.
I want to grab prices of products but some prices comes as .//p/span[#class='currency-value'] while other comes as .//p/span/span[#class='currency-value'] so I want to use OR exprssion for this
And I don't want price where product is for Advertise so I am using .//span[not(contains(text(),'Ad'))]
I have tried below xpath but its not working.
.//p/span[#class='currency-value'] | .//p/span/span[#class='currency-value'] and .//span[not(.='Ad')]
Rather than saying "try XXX" I think it's useful if you understand what's wrong with your current attempts.
.//p/span[#class='currency-value'] | .//p/span/span[#class='currency-value'] and .//span[not(.='Ad')]
The "|" operator in XPath means "union" - it forms the union of two node-sets. So //x | //y selects the union of the nodes selected by //x and those selected by //y. So far so good. You can simplify the "union" part of your expression to
(.//p/span | .//p/span/span)[#class='currency-value']
if you want.
The "and" is more problematic. The operands of "and" have to be booleans, whereas in your expression both operands are node-sets. I suspect (though I can't be sure) that your intent is to exclude from the union node-set those nodes that satisfy the predicate .='Ad' but without seeing your source data it's not clear how the products and prices relate to each other. Perhaps you intended this:
(.//p/span | .//p/span/span)[#class='currency-value'][not(.='Ad')]
or perhaps this:
(.//p/span | .//p/span/span)[#class='currency-value'][not(..='Ad')]
Either way, if I'm right that your intent is to exclude some of the nodes that would otherwise be selected, then an additional predicate is the way to do it.
After looking at the page, this CSS selector will work
div.hide-lg:not([data-behat-search-results-ads-xl]):not(.prolist-row) p > span.currency-value, div.hide-lg:not([data-behat-search-results-ads-xl]):not(.prolist-row) p > span > span.currency-value
Try this one. Do not overcomplicate with //p/span
//span[#class='currency-value'][not(.='Ad')]
Try this one. Combines #Vitaliy's answer with yours:
.//p/span[#class='currency-value'][not(.='Ad')] | .//p/span/span[#class='currency-value'][not(.='Ad')]
Please find the use of AND and OR in xpath as below:
this is the Page html:
<div class="mtlist-tab">
<ul class="wwf-tab-h">
<li class="tab-head">
<li class="tab-head on">
<li class="tab-head">
</ul>
</div>
if you are using AND in xpath where the two elements have same class class name then it will return 2 matching elements.
//li[#class='tab-head' and #class='tab-head']
if you are using AND in xpath where the two elements have different class class name then it will return 0 matching elements.
//li[#class='tab-head' and #class='tab-head on']
if you are using OR in xpath where the two elements have different class class name then it will return 3 matching elements(according to the HTML).
//li[#class='tab-head' OR #class='tab-head on']

Selenium: How to get text from within an html tag which has another tag in it

<a class="spf-link current" href="/orders/returns?offset=0&limit=25">
<span class="pg-helpText">Page</span>
1
</a>
I need to read the value '1' in my test. When I do a get text using css-selector .spf-link.current, it gets me "Page 1". I only need '1'. How do I exclude the text from the span tag.
You will need Javascript childNodes to get the text from the nodes.
The childNodes property returns a collection of a node's child nodes,
as a NodeList object.
The nodes in the collection are sorted as they appear in the source
code and can be accessed by index numbers. The index starts at 0.
WebElement element = driver.findElement(By
.cssSelector(".spf-link.current"));
String node_text=(String)((JavascriptExecutor)driver)
.executeScript("return arguments[0].childNodes[2].nodeValue",element);
This should give you the value 1 as node_text when you run the JavascriptExecutor. Other way is to split the text Page 1 on the basis of space. But, i would prefer childNodes.
Let me know if you have any queries.
Try the following:
//span[#class="pg-helpText" and contains(text(), 'Page')]/following-sibling::span/span
It is not normal to customize untagged text between tags.
I recommend you to change the value to your desired result:
<a class="spf-link current" href="/orders/returns?offset=0&limit=25">1</a>
...and when you want to show it in other place, do it as var ThePage = "Page " + [the page number]
Other solution is to include it into another tag as a div or as another span with a different class or id.