I'm using xpath's contains function to find elements that contain some text, like this:
//td[contains(text(),'foo')]
But if the page, for example, contains two td elements, that contain foo and foo bar respectively, the above xpath will return both of them.
Is there any kind of strict contains, that will return only the element with text foo, but not the one with foo bar?
By "strict contains" do you actually mean a simple equality test? If so you should be able to do that using //td[text() = 'foo'].
Try this way:-
//td[normalize-space() = 'foo']
Related
I have the following XML payload:
<fizz>
<buzz class="foo">
<whatever/>
</buzz>
</fizz>
The value of the /fizz/buzz[#class]/#class attribute can be foo, bar or whistlefeather. I'm trying to write an efficient XPath expression that covers all three scenarios. The best I have is:
/fizz/buzz[#class]/#class = 'foo' |
/fizz/buzz[#class]/#class = 'bar' |
/fizz/buzz[#class]/#class = 'whistlefeather'
Is there some "shorthand" way to make this more condense/efficient (less verbose)?
Using this (all xpath version) :
/fizz/buzz[#class='foo' or #class='bar' or #class='whistlefeather']
Using xpath >=2 :
/fizz/buzz[#class=("foo", "bar", "whistlefeather")]
Correcting the answer from #GillesQuenot:
Using any XPath version:
/fizz/buzz[#class='foo' or #class='bar' or #class='whistlefeather']
Using XPath 2.0 or later:
/fizz/buzz[#class=("foo", "bar", "whistlefeather")]
(Note, this returns the selected buzz elements. It's unclear what you actually want the expression to return.)
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*(.*)')
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()
Is it possible to do a 'and' condition in xpath like
//foo/bar/test[#val='hello'] and //foo/bar/new[#val='world']
This condition returns true for some reason and not any results. I've tried | but I don't need an or statement.
The results should return all the elements from //foo (where the conditions match) - I need the root element because I'll be pulling data out from different elements.
I'm using xpath to query an exist-db database
I need to put //foo[(position()> 3) and (position() < 6)] in there also.
If you want to get the foo elements, start the [] just after foo:
//foo[bar/test/#val='hello' and bar/new/#val='world']
If you want the children of foo, put the brackets there:
//foo/bar[test/#val='hello' and new/#val="world"]
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