Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

using child nodes as qualifiers in xpath, for selenium webdriver

I am using selenium webdriver in a Django (Python) app. My question is xpath however.

For some reason, schools have not standardized a central source to lookup transcript information, and thoroughly enjoy charging former students for the wonderful service of clicking a button, while requiring the paying party to do the work of ordering them. I am automating ordering them and came across this recent pattern which a function I wrote can't handle:

<a href="HTTPS://hccadvisor.hccfl.edu:443/WebAdvisor/WebAdvisor?TOKENIDX=4932326730&amp;type=P&amp;pid=UT-LGRQ" 
    onmouseover="window.status=''; return true;">
    <span class="label">Log In </span>
</a>

It must be grabbed each time, as the token is being tacked on in the middle.

My function was calling

def access_link_by_text(text, driver):
    block = driver.find_element_by_xpath("//a[text()='{text}']".format(text=text))
    link  = block.get_attribute('href')
    driver.get(link)

but at 2 of my other schools sites I see wrapping the text within spans:

login_block = hcc_driver.find_element_by_xpath("//a/span[text()='Log In ']")
login_link  = login_block.get_attribute('href')

Where login_link does not exist, as login_block is not grabbing the <a href... that I want it to. It grabs the span, since I said "any a's with span children whose text is Log In ". I want to grab the a using the child span as a test, so I tried:

login_block = hcc_driver.find_element_by_xpath("//a/child::span[text()='Log In ']")

which also failed.

How do you use children/parents/siblings as qualifying tests, without trying to pick them so I can get this link?

Thank you

like image 786
codyc4321 Avatar asked Nov 23 '25 17:11

codyc4321


1 Answers

Where login_link does not exist, as login_block is not grabbing the <a href... that I want it to. It grabs the span, since I said "any a's with span children whose text is Log In ". I want to grab the a using the child span as a test, so I tried:

You are close. You can nest predicates. The solution should be:

//a[child::span[text()='Log In ']]

Which will select every <a> in the document that has a span that has a text node with the text "Log In ". You may want to be careful about possible added whitespace, this is a bit safer:

//a[child::span[normalize-space(text())='Log In']]

And for the fun of it, you can also revert your expression, if you find that more readable:

span[normalize-space(text())='Log In']/parent::a
like image 84
Abel Avatar answered Nov 26 '25 06:11

Abel