Select unique set of nodes with XPath? - ruby-on-rails

I want to select a set of elements as nodes (the content of div[#class="Adres"]):
<div class="KolumnaStyl">
<div class="Nazwa">ABCD</div>
<div class="Adres">
12-345 Warszawa
<br/>
ul. Krasnobrodzka 5
<br/>
Mazowieckie
This can be done with:
//div[#class="KolumnaStyl"]/div[#class="Adres"]/node()
As it happens, there are two identical div[#class="Adres"] on the page, which means that node() currently selects the content of both of them. I can't, however, call //div[#class="KolumnaStyl"][1] - that doesn't select the first occurrence.
How can I select a unique set of nodes if the parent directory exists multiple times?

Take a look at "XPath Get first element of subset".
Basically, predicates have higher precedence than the / and // operators.
So, (//div[#class="KolumnaStyl"]//(div[#class="Adres"]))[1] should return your desired result.
Also check out the spec for more background info.

If you want the first matched one, then do :
(//div[#class="KolumnaStyl"]//div[#class="Adres"])[1]/node()
In XPATH first means 1, not 0.
Here is a sample HTML :
<body>
<div class="foo">
<p> 12 </p>
</div>
<div class="foo">
<p> 112 </p>
</div>
</body>
XPATH expression:
(//div[#class = 'foo'])[1]
output
<div class="foo">
<p>12</p>
</div>

Related

Capybara - usage of applying has_xpath? on an apath with variable

There is the structure like:
<div class="parent">
<div>
<div class="fieldRow">...</div>
</div>
<div>
<div class="fieldRow">
<div class="CheckBox">
</div>
</div>
<div>
<div class="fieldRow">...</div>
</div>
<div>
<div class="fieldRow">...</div>
</div>
</div>
In my script I am writing a loop for each of the 4 div's under div[#class='parent'] and aiming to click the checkbox if there is, i.e.
members = page.all(:xpath, '//div[#class='parent'])
members.each do |a|
if **page.has_xpath?(a).find(:xpath, "div[#class='fieldRow']/div[#class='CheckBox']")**
a.find(:xpath, "div[#class='fieldRow']/div[#class='CheckBox']").click
end
end
However I can't look for the correct usage of has_xpath? with xpath including variable.
Please advice? Thank you!
has_xpath? takes an XPath expression (not an element) and returns a boolean (true/false) based on whether there are any elements that match that expression within the current scope - http://www.rubydoc.info/gems/capybara/Capybara/Node/Matchers#has_xpath%3F-instance_method. Since it returns true/false you can't then call find on it. For the example you posted there's no need for XPath or checking for the existence of the elements, just find all the matching elements and call click on them. Something like
page.all('div.parent div.fieldRow div.Checkbox').each { |cb| cb.click }
or
page.all('div.parent div.Checkbox').each { |cb| cb.click }
if the fieldRow class isn't something you really need to check.
Note: this assumes clicking the elements doesn't invalidate any of the other matched elements/change the page.
If you REALLY need to do it with the whole members and looping on them , using XPath, and checking for presence then it would be something like
members = page.all(:xpath, './/div[#class='parent'])
members.each do |a|
if a.has_xpath?(:xpath, ".//div[#class='fieldRow']/div[#class='CheckBox']")
a.find(:xpath, ".//div[#class='fieldRow']/div[#class='CheckBox']").click
end
end
Note: the .// at the beginning of the XPath expressions is needed for scoping to work correctly - see https://github.com/teamcapybara/capybara#beware-the-xpath--trap - which is an issue using CSS selectors doesn't have, so you should really prefer CSS selectors whenever possible.

ASP.net MVC - Why each element on a different row?

I'm creating a simple ASP.net MVC form using bootstrap. My form looks like:
#using(Html.BeginForm()){
<div class="row">
<div class="col-md-4">#Html.TextBox("City", "", new { placeholder = "City" })</div>
<div class="col-md-4">#Html.TextBox("State", "", new { placeholder = "State", maxlength = "2" })</div>
<div class="col-md-4">#Html.TextBox("Zip", "", new { placeholder = "Zip Code" })</div>
</div>
}
Although I'm using appropriate classes for columns and textboxes should be inline, they are appearing in different rows. To my understanding, as long as the column widths are within a limit of 12 columns, inline elements should appear in the same row. Why is there a line break between these elements?
N.B: If I remove divs for individual columns and put all textboxes in a single div, they appear in the same row correctly.
To my understanding, as long as the column widths are within a limit
of 12 columns, inline elements should appear in the same row.
Cut off for col-md-x is 970px. It means if the browser size is less than 970px, they will be rendered as individual row. You can read here.
If you always want them to appear them in a single row, you want to use col-xs-x, or mix classes like this -
<div class="row">
<div class="col-sm-4 col-xs-12"></div>
<div class="col-sm-4 col-xs-12"></div>
<div class="col-sm-4 col-xs-12"></div>
</div>
If you want your textboxes inline, they should be put inside a single div tag. but if you want to put it in different divs, you can try to remove "col-md-4" in your divs and use css instead, like this:
.row {
display: flex;
}
Also, add some extra "padding" or "margin" property for spacing between those textboxes.
If there is anything wrong about my answer, please feel free to correct it. Thanks!

Extracting Image with CSQuery and then inserting it in front of heading tag

I was trying to use HTMLAgilityPack to manipulate some Html. I decided to try CSQuery as well.
The goal is to extract and img tag and it src and reinsert it in front of an h3 tag.
Assume html:
<div class="col-md-6">
<div class="item">
<div class="content galleryItem">
<h3>
Al Shabaab kill at least 29 in latest attacks on Kenyan coast
</h3>
<p> <img alt src="../../../../images/AlShabaab.jpg"></p>
<p>
Al Shabaab killed at least 29 people in two coastal areas of Kenya.</p>
</div>
</div>
</div>
Goal is to move the img in front of the h3
I used the following to strip the style attr from img tags:
Dim csq = CQ.Create(input)
Dim csstyle = csq("img")
Return csstyle.RemoveAttr("style")
Since you did not explicitly tag this VB.NET I'll answer in C#, I hope that's OK:
var cq = CQ.create(input); // create the CsQuery source
var img = cq["img"]; // image here, img["src"] is its source
img.Remove().InsertBefore(cq["h3"]);// remove it, and add it in front of H3.
of course this code can be shorter, but I wanted the code to match your literal description.

Can I use gr:category in GoodRelations and rdf:type from productontology together?

Can I use gr:category and rdf:type from product ontology together?
I see vso:Canoe from automobile ontology...
<div typeof="gr:SomeItems vso:Canoe" about="#product">
<span property="g:name">ACME Foldable Canoe</span>
<div property="gr:category" content="Outdoors/Boats/Canoes"></div>
</div>
However I'm using productontology,is this possible?
<div about="#myObject" typeof="http://www.productontology.org/id/Canoe">
<div rel="rdf:type" resource="http://purl.org/goodrelations/v1#SomeItems"></div>
<div property="gr:description" xml:lang="en">... a longer description ...</div>
<div property="gr:name" xml:lang="en">.. a short name for the object ...</div>
<div property="gr:category" content="Outdoors/Boats/Canoes"></div>
</div>
Yes, that is well possible and increases a client's ability to understand your data.
So
<div about="#myObject" typeof="http://www.productontology.org/id/Canoe">
<div rel="rdf:type" resource="http://purl.org/goodrelations/v1#SomeItems"></div>
<div property="gr:description" xml:lang="en">... a longer description ...</div>
<div property="gr:name" xml:lang="en">.. a short name for the object ...</div>
<div property="gr:category" content="Outdoors/Boats/Canoes"></div>
</div>
is perfectly valid.
There is currently no official statement from major search engines on the ways they honor additional type information, but it is a safe assumption that
it does not harm adn
the more data of this form is out there, the more it will matter for search engines.
Yes, you can use types and properties from any namespace in RDFa (and RDF in general). In the case of your snippet, you could even get rid of the rdf:type line since #typeof accepts multiple types from any number of namespaces, and those types can be in the form of CURIEs or full URIs (same applies to #property). So your snippet would become:
<div about="#myObject" typeof="http://www.productontology.org/id/Canoe gr:SomeItems">
<div property="gr:description" xml:lang="en">... a longer description ...</div>
<div property="gr:name" xml:lang="en">.. a short name for the object ...</div>
<div property="gr:category" content="Outdoors/Boats/Canoes"></div>
</div>

Inserting HTML elements on rails view

I have a view with a bunch of elements in it.One of them (a div) is shown depending of a value that changes inside a select_tag (also within the same page).
I'm getting the selected ID from the select_tag element
$('#some_id').on('change',function(){
//$(this).val()
})
but then just don't know how to fetch the object and check for one of its properties and that way know if I should show the div or not?.
I thought of sending that id to the server...do whatever I need over there and then come back to the view and try something like this
<% if some_condition %>
<div>
...
</div>
<% end %>
This (of course) might not be the way.I'd be glad to understand how this happens
You way of doing it after getting some data from the server onChange of the select would work. You might also consider this approach.
But if you could pre-populate the divs and add a class or some other attribute it with which you could relate to the chosen option in the select field, then you can prevent the server call entirely.
<div class="opt1Val selectOptsDiv"> </div>
<div class="opt2Val selectOptsDiv"> </div>
<div class="opt3Val selectOptsDiv"> </div>
hide all these divs initially with css display: none;.
$('#some_id').on('change',function(){
var selectedOptionVal = $(this).find("option:selected).val();
$("." + selectedOptionVal).show();
})
But I guess you would be able to do this if the showing and hiding of the div's depend only on the selected option value and do not have to go through some other processing at the server end.

Resources