How to take xpath to Get Text from class inside th - xpath

I have the following XPath :
//table[#class='ui-jqgrid-htable']/thead/tr/th//text()
And I'm trying to get the text from it with the following command :
String LabelName = driver.findElement(By.xpath("//table[#class='ui-jqgrid htable']/thead/tr/th//text()")).getText()
But it's not printing text, the result is blank. Could you help me please ?

The text() in your xpath does not qualify as an element. Your element ends at //table[#class='ui-jqgrid-htable']/thead/tr/th. Try using getText() for this XPath.
Also, a table would have many headers. Using findElement will only return the first one.
If you want to get all headers use
driver.findElements(By.xpath("//table[#class='ui-jqgrid-htable']/thead/tr/th"))
and loop through the list to getText of individual element.

Related

I'm trying to get the "id" of an html tag, but the xpath doesnt work

I'm using selenium and i want to get the "id" of an html tag with "find_elements_by_xpath", but i've got this error :
selenium.common.exceptions.InvalidSelectorException: Message: invalid
selector: The result of the xpath expression
"//body[contains(#class,'de')]/div/div[contains(#class,'container-fluid
default')]/section[contains(#id,'mainContent')]/div[contains(#class,'row-fluid')]/div[contains(#id,'contentContainer
row-fluid')]/div[contains(#class,'content')]/div[contains(#class,'ses')]/ul/li/#id"
is: [object Attr]. It should be an element.
When i executed this code:
browser.find_elements_by_xpath("//body[contains(#class,'de')]/div/div[contains(#class,'container-fluid default')]/section[contains(#id,'mainContent')]/div[contains(#class,'row-fluid')]/div[contains(#id,'contentContainer row-fluid')]/div[contains(#class,'content')]/div[contains(#class,'ses')]/ul/li/#id")
While the same code without "/#id" work perfectly but i've got only the text in the "li" tag and it's not what i want.
According to the error, the problem comes from the Xpath.
I expected that this code would return all the "id" that are in "li" html tag, but i got the error.
Thank you for your help
#id is an attribute, not an element. The XPath is OK, but the function only returns elements, not attributes. I doubt there's find_attributes_by_xpath, but if you want to find the li element that has the #id defined, you can specify that in the quantifier:
browser.find_elements_by_xpath("//body[contains(#class,'de')]
/div/div[contains(#class,'container-fluid default')]
/section[contains(#id,'mainContent')]
/div[contains(#class,'row-fluid')]
/div[contains(#id,'contentContainer row-fluid')]
/div[contains(#class,'content')]
/div[contains(#class,'ses')]/ul/li[#id]")
~~~~~
You can then call element.get_attribute('id') to retrieve the id of the element.

get only a part of text() with xpath

I'm trying to get the array of authors of this website:
http://www.intechopen.com/books/latest/1/list
with this xpath:
response.xpath("//div[#id='sizer']/div[#id='content']/div[#class='grid']/div[#class='main-content']/div[#id='tc']/div/ul[#class='book-listing entity-listing']/li/dl/dd[#class='meta']/text()[count(preceding-sibling::br) = 0]").extract()
but i want only the names, without the "editor", how can I do it?
After selecting the text, use the regular expression function re() with a capture group in order to exclude the text you do not want:
response.xpath("//div[#id='sizer']/div[#id='content']/div[#class='grid']/div[#class='main-content']/div[#id='tc']/div/ul[#class='book-listing entity-listing']/li/dl/dd[#class='meta']/text()[count(preceding-sibling::br) = 0]")
.re(r'Editor\s*(.*)')

Xpath get multiple node-names

i am using xpath to get some node names from a xhtml / xml file.
I currently have this xpath:
/xhtml:html/xhtml:head/xforms:model/xforms:instance/form/*[starts-with(local-name(), 'section')]
That will get the nodes with a name like this:
section-1_s1_partners
section-2-s2_strategy
The result of the above xpath are the matched nodes, but i want to get for each match the full-node-name. When i use the name() function like
name(/xhtml:html/xhtml:head/xforms:model/xforms:instance/form/*[starts-with(local-name(), 'section')])
Then it only returns the first match, and i have no clue how to do it otherwise..
Any great ideas??
Thanks!
(the xhtml/xml: )
<xhtml:html ....>
<xhtml:head>
<xhtml:title>ASD-1</xhtml:title>
<xforms:model id="fr-form-model">
<xforms:instance id="fr-form-instance">
<form>
<section-1_s1_partners>
<control-304/>
<toggleForm>ASD</toggleForm>
<applicationid/>
<section-345>
<s1_kbPaAAr/>
<s1_kbDCCent/>
<s1_kbRAE/>
</section-345>
<section-s1_depDDFentGFress>
<address_search/>
<address_postcode/>
<address_address1/>
<address_address2/>
<address_address3/>
<address_city/>
</section-s1_departmentAddress>
<section-344>
<s1_companyPartner/>
<s1_companyRegistrationNumber/>
<s1_companyType/>
<s1_companySize/>
</section-344>
<section-s1_companyAddress>
<address_search/>
<address_postcode/>
<address_address1/>
<address_address2/>
<address_address3/>
<address_city/>
</section-s1_companyAddress>
<section-324>
<s1_plannedDate/>
<s1_workDescription/>
<s1_publicDescription/>
<s1_numberOfAssociates>1</s1_numberOfAssociates>
<s1_duration/>
<s1b_resubmissionYesNo/>
<s1_GAAGrogramNumber/>
</section-324>
</section-1_s1_partners>
<section-2-s2_strategy>
<control-4/>
<s2_memo_strategic/>
<s2_memo_problems/>
<s2_companyPosition/>
<s2_companyContribution/>
<s2_lackExpertise/>
<s2_essential/>
<s2_companySponsor/>
<s2_seekKnowledge/>
<s2_challenge/>
</section-2-s2_strategy>
The name function need one argument, it cannot take a node list. You have to iterate over the nodelist in the language you are using. For example, in xsh:
for /xhtml:html/xhtml:head/xforms:model/xforms:instance/form/*[starts-with(local-name(), 'section')]
echo name()

Selenium Webdriver + Ruby regex: Can I use regex with find_element?

I am trying to click an element that changes per each order like so
edit_div_123
edit_div_124
edit_div_xxx
xxx = any three numbers
I have tried using regex like so:
#driver.find_element(:css, "#edit_order_#{\d*} > div.submit > button[name=\"commit\"]").click
#driver.find_element(:xpath, "//*[(#id = "edit_order_#{\d*}")]//button").click
Is this possible? Any other ways of doing this?
You cannot use Regexp, like the other answers have indicated.
Instead, you can use a nifty CSS Selector trick:
#driver.find_element(:css, "[id^=\"edit_order_\"] > div.submit > button[name=\"commit\"]").click
Using:
^= indicates to find the element with the value beginning with your criteria.
*= says the criteria should be found anywhere within the element's value
$= indicates to find the element with with your criteria at the end of the value.
~= allows you to find the element based on a single criteria when the actual value has multiple space-seperated list of values.
Take a look at http://net.tutsplus.com/tutorials/html-css-techniques/the-30-css-selectors-you-must-memorize/ for some more info on other neat CSS tricks you should add to your utility belt!
You have no provided any html fragment that you are working on. Hence my answer is just based on the limited inputs provided your question.
I don't think WebDriver APIs support regex for locating elements. However, you can achieve what you want using just plain XPath as follows:
//*[starts-with(#id, 'edit_div_')]//button
Explanation: Above xpath will try to search all <button> nodes present under all elements whose id attribute starts with string edit_div_
In short, you can use starts-with() xpath function in order to match element with id format as edit_div_ followed by any number of characters
No, you can not.
But you should do something like this:
function hasClass(element, className) {
var re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)');
return re.test(element.className);
}
This worked for me
#driver.find_element(:xpath, "//a[contains(#href, 'person')]").click

How to get H1,H2,H3,... using a single xpath expression

How can I get H1,H2,H3 contents in one single xpath expression?
I know I could do this.
//html/body/h1/text()
//html/body/h2/text()
//html/body/h3/text()
and so on.
Use:
/html/body/*[self::h1 or self::h2 or self::h3]/text()
The following expression is incorrect:
//html/body/*[local-name() = "h1"
or local-name() = "h2"
or local-name() = "h3"]/text()
because it may select text nodes that are children of unwanted:h1, different:h2, someWeirdNamespace:h3.
Another recommendation: Always avoid using // when the structure of the XML document is statically known. Using // most often results in significant inefficiencies because it causes the complete document (sub)tree roted in the context node to be traversed.

Resources