What is wrong with my path to select the following:
<label class="form-control-label" for="profile_form_state">State</label>
Xpath:
xpath = '//label[ends-with(#for, "_state")]'
I am using rspec and capybara
expect(rendered).to have_xpath(xpath)
Error:
xmlXPathCompOpEval: function ends-with not found
As answered by #har07, XPath 1.0 (which browsers implement) doesn’t have an ends-with but CSS provides an ends-with attribute selector $=
expect(rendered).to have_css(‘label[for$=“_state”]’)
or you can use regex with Capybaras built-in :label selector
expect(rendered).to have_selector(:label, for: /_state$/)
If you really want to stick with XPath over CSS then you can use the xpath gem Capybara uses internally for generating its own XPaths and write
xpath = XPath.descendant(:label).where(XPath.attr(:for).ends_with('_start'))
expect(rendered).to have_xpath(xpath)
Looks like your XPath processor only supports XPath, 1.0 while ends-with is defined in XPath 2.0 and above. But you can simulate ends-with() in XPath 1.0 using substring() and string-length() :
xpath = '//label["_state" = substring(#for, string-length(#for) - string-length("_state") +1)]'
You can shorten the expression a bit by replacing string-length("_state") +1 with pre-calculated value 5 (length of the word _state minus one) :
xpath = '//label["_state" = substring(#for, string-length(#for) - 5)]'
Try the following Xpath.
xpath = '//label[contains(., "State")]'
Other possible Xpath
//label[contains(#for, '_state')]
or
//label[text()='State']
or
//label[contains(text(), 'State')]
Related
in this HTML using scrapy i can access the full info-car by : './/#info-car' XPath
<div class="car car-root"
info-car='{brand":"BMW","Price":"田"name":"X5","color":null,"}'>
</div>
what is the XPath to pick only the name of info-car ?
You can obtain the name by using a combination of xpath and regex. See below sample code:
response.xpath(".//#info-car").re_first(r'"name":"(.*)",')
<p><span class="label">key</span>value</p>
How am I able to get just the "value" out using xPath? I managed to get to the element using the following expression:
//span[#class='label']/..
Try this one to get required value:
//p[span[#class='label']]/text()
You just have to use text() to get the text from the p
//span[#class='label']/../text()
div class="ydpbfddd73dsignature" >......
How do I use xpath to get whatever text comes after this tag?
I tried doing this
nokogiri_html=Nokogiri::HTML html
nokogiri_html.xpath('//div[#class="/.*signature/"]')
But it doesn't work.
You can apply below XPath:
//div[substring(#class, string-length(#class) - 8)="signature"]
which means return div node which has "signature" as last 9 characters of class name
XPath expression:
'.//div/concat(#id, " - ", #class)'
fails with an error:
The expression is not a legal expression.
in Firefox 25.0 (from a userscript).
Why, and how to fix?
For input:
<div id='id1' class='class1'>
sample
</div>
<div id='id2' class='class2'>
sample
</div>
I'd like to get two separate strings:
id1 - class1
id2 - class2
Firefox only supports XPath 1.0, but your expression requires XPath 2.0. There's no equivalent in XPath 1.0 (your expression returns a sequence of strings, which is a data type that doesn't exist in XPath 1.0).
Are you calling this XPath from XSLT or from Javascript? Either way, you will have to do the work in the host language rather than in XPath.
I think you should do as below:
HTML
<div id='foo' class='bax'>
sample
</div>
XPATH
concat(//div/#id, " - ",//div/#class)
or
(//div)/concat(#id,' - ',#class)
output
foo - bax
I have a quite simple problem but i can't seem to resolve it. Let's say i have the following code:
<a>
<b property="p1">zyx</b>
<b>wvu</b>
<b>tsr</b>
<b property="p2">qpo</b>
<b>qcs</b>
</a>
I want to select the nodes between the b node who has a property="p1" and the b node who has property="p2". I can do either of those with the preceding-sibling and the following-sibling axis but I can't seem to find how to combine both.
XPath 1.0:
/a/b[preceding-sibling::b/#property='p1' and following-sibling::b/#property='p2']
XPath 2.0:
The expression above has some quirks in XSLT 2.0, it is better to use the new and safer operators << (before) and >> (after).
/a/b[../b[#property='p2'] << . and . >> ../b[#property='p1']]
Also, this XPath 1.0:
/a/b[preceding-sibling::b/#property='p1'][following-sibling::b/#property='p2']
Note: Don't use // as first step. Whenever you can replace and operator by predicates, do it.
In XPath 2.0:
/a/b[. >> ../b[#property='p1']][../b[#property='p2'] >> .]
You can combine the tests in the predicate using and.