I have following markup (schema.org attributes included):
<body>
<div itemscope itemtype="http://schema.org/Foo">
<div>
<div itemname="name">
Foo scoped name
</div>
</div>
<div>
<div itemscope itemtype="http://schema.org/Bar">
<div>
<div itemname="name">
Bar scoped name
</div>
</div>
</div>
</div>
</div>
</body>
I need to select (presumably by xpath as css selectors won't be enough for the task) divs that have itemname="name" in http://schema.org/Foo scope but not those that have another element with itemscope attribute ascending them.
So in example provided I need to select only "Foo scoped name", but not "Bar scoped name".
You can use something like :
//div[#itemname="name"][ancestor::div[#itemscope][1][#itemtype="http://schema.org/Foo"]]
Look for a div element with a specific attribute value (#itemname="name"). Its first div ancestor (with #itemscope attribute) contains also a specific #itemtype attribute value (http://schema.org/Foo).
Output : <div itemname="name"> Foo scoped name </div>
Related
I am trying to enter text into an input field and can not successfully get it working. I have two inputs that look like this:
<div class"outerParentClass">
<div class="classLabel">From</div>
<div class="classA classB classD">
<div class="classE">
<div class="classText"> TEXT HERE </div>
<input class="classInputA classInoutB" type="text">
</div>
</div>
</div>
<div class="classLabel">To</div>
<div class="classA classB classD">
<div class="classE">
<div class="classText"> DIFFERENT TEXT HERE </div>
<input class="classInputA classInoutB" type="text">
</div>
</div>
</div>
</div>
Both the inputs are the exact same format as above. There are no Id's and both have the same classes. I am struggling at entering the text into these or even finding them correctly.
When I do this:
browser.text_field(:class => "classInputA").size
It returns 20
When I do this:
browser.text_field(:class => "classInputA")
It returns:
#<Watir::TextField:0x..fbccafb7ed2e9b85e located=false selector={:class=>"classInputA", :tag_name=>"input"}>
Not sure how to locate either of these inputs. Any suggestions?
The text adjacent to the field provides a label and context for the field. As it is likely unique, you can use this to identify the element.
To do this, find the div containing the label text. Then navigate to the adjacent div that contains the text field.
browser.div(text: 'From', class: 'classLabel') # label of interest
.element(xpath: './following-sibling::div[1]') # adjacent div containing text field
.text_field # the text field
Note that in the next release of Watir, .element(xpath: './following-sibling::div[1]') will be replaceable by just .following-sibling.
Below is my html
<div class="right" data-bindattr-13="13">
<h3>Company Name</h3>
<div class="input-row">
<input id="ember4258" class="ember-view ember-text-field" type="text"/>
</div>
<h3>Full Company Legal Name</h3>
<div class="input-row">
<input id="ember4259" class="ember-view ember-text-field" type="text"/>
</div>
<h3>Company Phone</h3>
<div class="input-row">
<input id="ember4260" class="ember-view ember-text-field" type="text"/>
</div>
<h3>Federal Tax / Employer ID (EIN)</h3>
<div class="input-row">
<input id="ember4261" class="ember-view ember-text-field" type="text"/>
</div>
</div>
Since class value off all the text fields and respective parent div class attributes are same I need to fill these text fields without using nth-of-type.
I have done work around to create a CSS selector that should point the text box that is immediately after <h3>Full Company Legal Name</h3> .
h3:contains(^Company Name$)+div>input
But my Capybara script is not recognizing the above way and throwing the below error.
annotateInvalidSelectorError_': The given selector h3:contains(^Company Name$)+div>input is either invalid or does not result in a WebElement. The following error occurred: (Selenium::WebDriver::Error::InvalidSelectorError)
InvalidSelectorError: An invalid or illegal selector was specified
Can any one provide a CSS that matches my requirement?
Regards,
Avinash Duggirala
The contains pseudo class was deprecated, which is why the InvalidSelectorError occurs. There is currently no way to check text nodes using CSS-selectors.
Instead, you can use XPath to traverse the DOM to sibling elements.
text_field = page.find(:xpath, '//h3[text() = "Company Name"]/following-sibling::div[1]/input')
text_field.set('some value')
I am new to nokogiri and so far most familiar with CSS selectors, I am trying to parse information from a table, below is a sample of the table and the code I'm using, I'm stuck on the appropriate if statement, as it seems to return the whole contents of the table.
Table:
<div class="holder">
<div class ="row">
<div class="c1">
<!-- Content I Don't need -->
</div>
<div class="c2">
<span class="data">
<!-- Content I Don't Need -->
<span class="data">
</div>
</div>
...
<div class="row">
<div class="c1">
SPECIFIC TEXT
</div>
<div class="c2">
<span class="data">
What I want
</span>
</div>
</div>
</div>
My Script: (if SPECIFIC TEXT is found in the table it returns every "div.c2 span.data" variable - so I've either screwed up my knowledge of do loops or if statements)
data = []
page.agent.get(url)
page.search('div.row').each do |row_data|
if (row_data.search('div.c1:contains("/SPECIFIC TEXT/")').text.strip
temp = row_data.search('div.c2 span.data').text.strip
data << temp
end
end
There's no need to stop and insert ruby logic when you can extract what you need in a single CSS selector.
data = page.search('div.row > div.c1:contains("SPECIFIC TEXT") + div.c2 span.data')
This will include only those that match the selector (e.g. follow the SPECIFIC TEXT).
Here's where your logic may have gone wrong:
This code
if (row_data.search('div.c1:contains("SPECIFIC TEXT")'...
temp = row_data.search('div.c2 span.data')...
first searches the row for the specific text, then if it matches, returns ALL rows matching the second query, which has the same starting point. The key is the + in the CSS selector above which will return elements immediately following (e.g. the next sibling element). I'm making an assumption, of course, that the next element is always what you want.
I'd do
require 'nokogiri'
html = <<_
<div class="holder">
<div class ="row">
<div class="c1">
<!-- Content I Don't need -->
</div>
<div class="c2">
<span class="data">
<!-- Content I Don't Need -->
<span class="data">
</div>
</div>
<div class="row">
<div class="c1">
SPECIFIC TEXT
</div>
<div class="c2">
<span class="data">
What I want
</span>
</div>
</div>
</div>
_
doc = Nokogiri::HTML(html)
css_string = 'div.row > div.c1[text()*="SPECIFIC TEXT"] + div.c2 span.data'
doc.at(css_string).text.strip
# => "What I want"
How those selectors would work here -
[name*="value"] - Selects elements that have the specified attribute with a value containing the a given substring.
Child Selector (“parent > child”) - Selects all direct child elements specified by "child" of elements specified by "parent".
Next Adjacent Selector (“prev + next”) - Selects all next elements matching "next" that are immediately preceded by a sibling "prev".
Class Selector (“.class”) - Selects all elements with the given class.
Descendant Selector (“ancestor descendant”) - Selects all elements that are descendants of a given ancestor.
How can I get the element data using jsoup or xpath.
My requirement is
if i have selected class='SecondClass' then how to find its parent "FirstClass". Means if i have selected class="SecondClass">yyyyyyyyy then how to find
class="FirstClass">Hi element
<div class="FirstClass">Hello</div>
<div class="SecondClass">xyza</div>
<div class="SecondClass">lllllllll</div>
<div class="FirstClass">Hi</div>
<div class="SecondClass">ooooooooo</div>
<div class="SecondClass">yyyyyyyyy</div>
<div class="SecondClass">ttttttttyt</div>
<div class="FirstClass">HelloHi</div>
<div class="SecondClass">xysefsfza</div>
<div class="SecondClass">hohoho</div>
<div class="SecondClass">xydadaza</div>
<div class="SecondClass">new</div>
You can try this XPath expression to get nearest preceding <div> element having class attribute value equals FirstClass :
/preceding-sibling::div[#class='FirstClass'][1]
With that, given XML data is as posted in question, and current element is this :
<div class="SecondClass">yyyyyyyyy</div>
XPath query above will return this element :
<div class="FirstClass">Hi</div>
Here is the code:
<li class="abc">
<div class="abc">
<input type="checkbox">
</div>
<div class="xyz">
<div class="headline">Mongo like candy</div>
<div>
</li>
<li class="abc">
<div class="abc">
<input type="checkbox">
</div>
<div class="xyz">
<div class="headline">Candygram for mongo</div>
<div>
</li>
Xpath challenge. I want locate the checkbox of the li which contains the headline "Mongo like candy" so I can select it using Selenium. In other words, how do you locate the checkbox from here:
li//div[#class='abc']//input[#type='checkbox']
but qualifying it with a different attribute within the same parent node:
li//div[#headline][contains(text(),"Mongo like candy")]
The basic idea is to qualify the final path with a predicate, i.e.
li[/*predicate here*/]//div[#class='abc']//input[#type='checkbox']
The predicate expresses the condition on the li that you want:
.//div[#class='headline' and contains(text(), "Mongo like candy")]
Putting them together yields:
li[.//div[#class='headline' and contains(text(), "Mongo like candy")]]//div[#class='abc']//input[#type='checkbox']
something like
li[div[#class='xyz']//div[#class='headline' and contains(text(),"Mongo like candy"))]]//input[#type='checkbox']
unless I messed up parentheses. (that is, you select not just li, but the proper li).
Even this works:
//li[1]/div[1]/input[#type='checkbox']
It may fail if more div tags are introduced in the page.