I have a date picker on my website,
It contains a list of elements for each week
and then those include 7 elements for each day
2930311234
Now I'm trying to xpath find the last button with class "is-selected"
And I'd also like to go trough each week since I want the last possible date ( "is-selected" means avaible)
I've tried
.//div[#'available-dates-calendar']//table/?[last()='True']//button[last()='True']
But that gave me the first element...
For the last() condition to work, I think that you would have to use the spy to create a XPath query that finds all buttons.
When such a query is found, then you can use the last() condition to find the last in the list of items found.
Hope this helps.
I believe you can use the [-1] identifier to grab the last element. So, instead of [last()='True'], use [-1].
Related
I am trying to write an XPath expression which can return the URL associated with the next page of a search.
The URL which leads to the next page of the search is always the href in the a tag following the tag span class="navCurrentPage" I have been trying to use a following-sibling term to pull the next URL. My search in the Chrome console is:
$x('//span[#class="navCurrentPage"][1]/following-sibling::a/#href[1]')
I thought by specifying #href[1] I would only get back one URL (thinking the [1] chooses the first element in list), but instead Chrome (and Scrapy) are returning four URLs. I don't understand why. Please help me to understand how to select the one URL that I am looking for.
Here is the URL where you can find the HTML giving me trouble:
https://www.yachtworld.com/core/listing/cache/searchResults.jsp?cit=true&slim=quick&ybw=&sm=3&searchtype=advancedsearch&Ntk=boatsEN&Ntt=&is=false&man=&hmid=102&ftid=101&enid=0&type=%28Sail%29&fromLength=35&toLength=50&fromYear=1985&toYear=2010&fromPrice=&toPrice=&luom=126¤cyid=100&city=&rid=100&rid=101&rid=104&rid=105&rid=107&rid=108&rid=112&rid=114&rid=115&rid=116&rid=128&rid=130&rid=153&pbsint=&boatsAddedSelected=-1
Thank you for the help.
Operator precedence: //x[1] means /descendant-or-self::node()/child::x[1] which finds every descendant x that is the first child of its parent. You want (//x)[1] which finds the first node among all the descendants named x.
xpath index will apply on all matching records, if you want to get only the first item, get the first instance.
$x('//span[#class="navCurrentPage"][1]/following-sibling::a/#href[1]').extract_first()
just add, .extract_first() or .get() to fetch the first item.
see the scrapy documentation here.
I've found this very helpful to make sure you have the bracket in the right place.
What is the XPath expression to find only the first occurrence?
also, the first occurrence may be [0] not [1]
On this page
https://en.wikipedia.org/wiki/Trinity_Seven#Episode_list
I have:
//*[text()='Reception']//preceding::th[contains(#id, 'ep')]//following::I
But it only registers following.
The default firepath selector is: .//*[#id='mw-content-text']/div/table[5]/tbody/tr/td[1]/I but this kind of selector is known to break quite frequently. Just wondering if there is a better way of doing this and I thought this might be a way.
Thanks!
:)
- You can see that it's getting stuff under the table which is not what I want :S
Try to use below XPath to match required elements:
//th[contains(#id, 'ep')]/following::I[./following::*[text()='Reception']]
This looks more simple
//tr[contains(#class, 'vevent')]//i
Don't overcomplicate things. You need I tag inside each row. So just find row locator tr[contains(#class, 'vevent')] and get it's I
Another good approach in case you want to check that inside of parent element is located some special element, but you want to find some 3rd element is to use such style: //element[./specific]//child , so in your case:
//tr[contains(#class, 'vevent')][./th[contains(#id,'ep')]]//i
so it's I tag inside row that contains #id,'ep' in header
I'm trying to get the current position of a xpath match. Here is a real world example
on this page http://newyork.backpage.com/homes-for-sale/
running the following xpath matches the 8th listing counting from top
//div[contains(#class, 'cat 93893742')]
I want to somehow get the ad position using xpath which at the time of posting this question is "8". I tried using prececeding-sibling::div but I am getting unexpected results.
Anyway to achieve this with xpath?
I'm not sure wether current version of htmlunit supports XPath 2.0, but if so you can use below expression:
index-of(//div[starts-with(#class, "cat")], //div[#class='cat 93893742'])
This will return 10 - position in common list
If you want to get position in list for specific date (Thu. May. 11) you can try:
index-of(//div[normalize-space()="Thu. May. 11"]/following::div[starts-with(#class, "cat")],//div[normalize-space()="Thu. May. 11"]/following::div[#class='cat 93893742'])
which returns 8
Some description added in #har07 answer
I think this is what you required
count(//div[contains(#class, 'cat 93893742')]/preceding-sibling::div[starts-with(#class,'cat')])+1
Lets breakdown the whole
//div[contains(#class, 'cat 93893742')]
will match the required context node which have classname = cat 93893742
/preceding-sibling::div[starts-with(#class,'cat')]
Will match the all div element starts with classname=cat just before your context node
So if we keep all those in count() it will count all div tag just before the context node So add 1 to include count of context node as well
If you want to point that element by using index like calculated above then add this
//div[starts-with(#class,'cat')][count(//div[contains(#class, 'cat 93893742')]/preceding-sibling::div[starts-with(#class,'cat')])+1]
Equal to
//div[starts-with(#class,'cat')][10] // 10 in index number
Based on this and your previous question, maybe the following XPath is what you're looking for :
count(
//div[contains(#class, 'cat 93893742')]/preceding-sibling::div[contains(#class, 'cat ')]
)+1
I am trying to quickly find a specific node using XPath but it seems my multiple predicates are not working. The div I need has a specific class, but there are 3 others that have it. I want to select the fourth one so I did the following:
//div[#class='myCLass' and 4]
However the "4" is being ignored. Any help? I am new to XPath.
Thanks.
If a xpath query returns a node set you can always use the [OFFSET] operator to access a certain element of it.
Use the following query to access the fourth element that matches the #class='myClass' predicate:
//div[#class='myCLass'][4]
#WilliamNarmontas answer might be an alternative to the syntax showed above.
Alternatively,
//div[#class='myCLass' and position()=4]
The accepted answer works correctly only if all of the div elements have the same parent. Otherwise use:
(//div[#class='myCLass'])[4]
I am trying to find XPath of an element which has no attribute. It can only be identified by its parent's attribute. However, the parent also does not have unique attribute.
Eg: //*[#id="btn"][1]/ul/li[2]/a/span
Here there are 2 elements with id=btn. How do i get the 2nd element. The above syntax gives me 1st element.. However if i use:
//*[#id="btn"][2]/ul/li[2]/a/span
I get an error message
"The xpath expression '//*[#id="btn"][2]/ul/li[2]/a/span' cannot be evaluated or does not result in a WebElement "
Try this, you select those two first, then use brackets around and index them.
(//*[#id="btn"]/ul/li[2]/a/span)[2]
By the way, it's not a good practice to have multiple elements sharing same ids, if you are the developer, may consider change them.