What will be the xpath? - xpath

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>

Related

XPath - exclude descendants of specific selector

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>

XPATH: Select a node whose children do not containg some text

I'm trying to select a node whose children do not contain some specific text.
For example:
<div class="b-margin">
<div class="tag">Pt</div>
<div class="tag">En</div>
</div>
<div class="b-margin">
<div class="tag">Ru</div>
<div class="tag">En</div>
</div>
How would i go about selecting the 'div class="b-margin"' nodes that do not have children with the text "Pt"?
Here is the simple xpath.
//div[#class='b-margin' and not(div[.='Pt'])]
Screenshot:

Need to select a checkbox, based on text in another div

<div class="bli-category">
<div class="row ng-scope" ng-repeat="placementtrack by $index">
<div class="col-sm-12">
<div class="col-sm-1 bli-category-checkbox">
<input class="bli-check-box ng-valid" type="checkbox" ng-click="addPlacement" ng-checked="checkedPlacementIndex" ng-model="selectedPlacement">
</div>
<div class="col-sm-8 bli-category-content">
<div class="ng-binding" ng-bind="placement.placementName">page_details</div>
</div>
</div>
</div>
I need to select the checkbox in class='bli-check-box ng-valid' for the text in class='ng-binding'
When I try to get the xpath like
//input[#class='bli-check-box ng-valid']
it selects all the 4-5 checkboxes
To select the checkbox in class='bli-check-box ng-valid' with respect to the text in class='ng-binding' i.e. page_details you can use the following xpath :
//div[#class='bli-category']//div[#class='ng-binding' and contains(.,'page_details')]//preceding::input[#class='bli-check-box ng-valid']
Note : As the element is an Angular element you have to induce wait for the element to be clickable before attempting to click.
//div[text='page_detials' and class='ng-binding']/../preceding-sibling::div//input[class='bli-check-box ng-valid']
The above xpath starts with finding the node which has the custom text that you know. It then traverses to its parent and then its previous sibling which in your case houses your required input node. So after traversing to the div you select its child which is your required input node.

nokogiri + mechanize css selector by text

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.

In ruby when I try mytext.include? (">Model number<") is returning false

In ruby when I try mytext.include?(">Model number<") is returning false.
But mytext.include?("Model number") is returning true
What is wrong in the first condition?
mytext contains the string "Model number" inside ">" and "<"
This is relevant HTML:
<div class="bucket"> <div class="h1"><strong>Product Specifications</strong></div> <div class="content"> <div class="tsSectionHeader">Product Information</div> <div class="tsTable"> <div class="tsRow"><span class="tsLabel">Model number</span><span>516C</span></div> <div class="tsRow"><span class="tsLabel">Maximum weight recommendation</span><span>35 Pounds</span></div> <div class="tsRow"><span class="tsLabel">Material Type</span><span>Wood</span></div> </div> </div> </div>
You have to learn some HTML. > and < are part of span tag: <span></span>.
This is where the text appears:
<span class="tsLabel">Model number</span>
So a span has text Model number. You can get the text using Watir with this:
browser.span(:class => "tsLabel").text

Resources