Select a radio button by text using XPath - xpath

<div class="btm0">Question 1
</div><span class="small"></span>
<span id="form2">
<span id="form2:j_idt4598" style="display: none;"></span><ul id="form2:radioButton" class="controls full-width">
<li>
<input class=" firepath-matching-node" name="form2:radioButton" id="form2:radioButton:0" type="radio"><label for="form2:radioButton:0"> Yes</label></li>
<li>
<input class=" firepath-matching-node" name="form2:radioButton" id="form2:radioButton:1" type="radio"><label for="form2:radioButton:1"> No</label></li>
</ul>
<span id="form2:errMessage"></span>
</span>
<div class="btm0">Question 2
</div><span class="small"></span>
<span id="form1">
<span id="form1:j_idt4617" style="display: none;"></span><ul id="form1:radioButton" class="controls full-width">
<li>
<input class=" firepath-matching-node" name="form1:radioButton" id="form1:radioButton:0" type="radio"><label for="form1:radioButton:0"> Yes</label></li>
<li>
<input class=" firepath-matching-node" name="form1:radioButton" id="form1:radioButton:1" type="radio"><label for="form1:radioButton:1"> No</label>
I have this above simple page having a label and option button.
I want to select the 'Question 1 - Yes' using an XPath.
Is there an easy way to create a unique XPath, which will select the correct 'YES' option (which could be Question 1 or Question 2)? I don´t want to hardcode the XPath.
I tried out a partial solution but I only get the second 'YES' option selected:
//*[contains(text(),'Question 1')]/following::label[contains(text(),'Yes')]

Not sure if this is what you are asking, but if you want to limit the scope of your XPath expression to just the 2 label elements after the div, you can use the position() function:
//div[contains(text(),'Question 1')]/following::label[position() <= 2 and contains(text(),'Yes')]
If this is not what you are looking for, please try to clarify your question, perhaps by providing some sample results.

I was able to get some solution after try, but really not happy with the answer as I have to to change my xpath based on YES or NO of option button
for YES :
//*[contains(text(),'Question 1')]/./following::li[1]/label[contains(text(),'Yes')]
for NO :
//*[contains(text(),'Question 1')]/./following::li[2]/label[contains(text(),'Yes')]
As you see in the above solution, I have to toggle the values of li[].
But with above solution, I am able to pinpoint the option.

Related

xpath retrieve element that occur after parent element

I need to click on the element that appears after <span class="clientadress">
It can be either <div class="homephone"> or <input type="text">.
I try xpath /following:: or /child:: but it doesn't work.
Is it possible to do something like //following::(div or input)
Example of element order:
<span class="client">
<span class="clientadress">
<div class="homephone">
</span>
or
<span class="client">
<span class="clientadress">
<input type="text">
</span>
Try using
//span[#class="clientadress"]/(following-sibling::div | following-sibling::input)
and see if it works.
Try-Xpath in Firefox gives better results sometimes:
https://addons.mozilla.org/nl/firefox/addon/try-xpath/?utm_source=addons.mozilla.org&utm_medium=referral&utm_content=search
Jack gave me an idea and next is working for me: //following-sibling::*
Thank you all

Python/Plone: Getting all keywords and showing for EDIT content is very slow

Python/Plone: Getting all keywords and showing for EDIT content is very slow (keywords.pt)
No of keywords is 20000 so traversing these huge no of keywords is taking one minute.
Keywords which no has grown large is taking time....any solution is welcomed
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:tal="http://xml.zope.org/namespaces/tal"
xmlns:metal="http://xml.zope.org/namespaces/metal"
xmlns:i18n="http://xml.zope.org/namespaces/i18n"
i18n:domain="plone">
<head><title></title></head>
<body>
<!-- Keyword Widgets -->
<metal:view_macro define-macro="view"
tal:define="kssClassesView context/##kss_field_decorator_view;
getKssClasses nocall:kssClassesView/getKssClassesInlineEditable;">
<div metal:define-macro="keyword-field-view"
tal:define="kss_class python:getKssClasses(fieldName,
templateId='widgets/keyword', macro='keyword-field-view');
uid context/UID|nothing"
tal:attributes="class kss_class;
id string:parent-fieldname-$fieldName-$uid">
<ul metal:define-slot="inside">
<li tal:repeat="item accessor"
tal:content="item"/>
</ul>
</div>
</metal:view_macro>
<metal:define define-macro="edit">
<metal:use use-macro="field_macro | context/widgets/field/macros/edit">
<tal:define metal:fill-slot="widget_body" define="contentKeywords accessor;
allowedKeywords python: context.collectKeywords(fieldName, field.accessor, widget.vocab_source);
site_props context/portal_properties/site_properties|nothing;
format widget/format | string:select;
allowRolesToAddKeywords site_props/allowRolesToAddKeywords|nothing;">
<div tal:condition="allowedKeywords" id="existingTagsSection">
<tal:comment tal:replace="nothing">
dl semantically associates selector name with values
</tal:comment>
<dl id="existingTags">
<label for="subject">
<dt id="existingTagsTitle">uuuuuuuuuuuuuuuuuuuuuuuuu
<span i18n:translate="label_select_existing_tags">
Select from existing tags.
</span>
</dt>
<span id="existingTagsHelp" class="formHelp" i18n:translate="label_existingTagsHelp">
Use Control/Command/Shift keys to select multiple tags.
</span>
<tal:comment tal:replace="nothing">
Type-to-skip functionality with javascript enabled
could be described as
"Hover and type the first letter to skip through tags."
However, on touch-driven devices, vertical hover typically
scrolls the page, so horizontal hover is necessary to enable this.
Alternatively, clicking any of the tags also enables type-to-skip.
So the help could technically be extended to handle this special case
as "Hover or click and type the first letter to skip through tags.",
but I think this would be confusing to the majority of users.
The decision at this point is to not try to explain any of this on the page.
</tal:comment>
</label>
<div class="visualClear"><!-- --></div>
<select id="predefined_subjects"
name="predefined_subjects:list"
size="14"
multiple="multiple"
tal:condition="python:format!='checkbox'"
tal:attributes="id string:${fieldName};
name string:${fieldName}_existing_keywords:list;">
<option value="#" tal:repeat="keyword allowedKeywords"
tal:content="keyword" tal:attributes="value keyword;
selected python:test(context.unicodeTestIn(keyword, value), 'selected', None)">
An existing tag
</option>
</select>
<tal:comment tal:replace="nothing">
These spans are hidden by css, and used by the JavaScript called below.
</tal:comment>
<span id="noTagsSelected" i18n:translate="label_noTagsSelected">No tags currently selected.</span>
<span id="oneOrMoreTagsSelected" i18n:translate="label_oneOrMoreTagsSelected">% tags currently selected.</span>
<tal:comment tal:replace="nothing">
Call js to modify this widget with both a scrollbar and checkboxes.
There may be a better place to put this js call;
examples exist in others' widget.py and js files,
but having it here covers cases where some but not all select elements
call js to be modified.
Todo: The #subject should eventually refer to the template variable.
</tal:comment>
<script type="text/javascript">
jq(document).ready( function() {
jq("#subject").multiSelect();
});
</script>
<input type="hidden"
value=""
tal:condition="not:field/required | nothing"
tal:attributes="name string:${fieldName}_existing_keywords:default:list" />
<tal:loop tal:repeat="keyword allowedKeywords"
tal:condition="python:format=='checkbox'">
<div class="ArchetypesKeywordValue" id=""
tal:attributes="id string:archetypes-value-${fieldName}_${repeat/keyword/number}">
<input class="blurrable"
tal:attributes="
type string:checkbox;
name string:${fieldName}_existing_keywords:list;
id string:${fieldName}_${repeat/keyword/number};
checked python:test(context.unicodeTestIn(keyword, value), 'checked', None);
value keyword" />
<label
tal:content="keyword"
tal:attributes="for string:${fieldName}_${repeat/keyword/number}">
An existing tag
</label>
</div>
</tal:loop>
</dl>
<dl id="selectedTagsSection">
<dt id="selectedTagsHeading" class="formHelp"></dt>
<dd id="selectedTags"></dd>
</dl>
<div class="visualClear"><!-- --></div>
</div>
<!-- <tal:condition condition="python:not widget.roleBasedAdd or (allowRolesToAddKeywords and [role for role in user.getRolesInContext(context) if role in allowRolesToAddKeywords])">-->
<dl id="newTagsSection">
<label for="subject_keywords">
<dt id="newTagsTitle">
<span i18n:translate="label_create_new_tags">
Create and apply new tags.
</span>
</dt>
<span id="newTagsHelp" i18n:translate="label_newTagsHelp" class="formHelp">
Enter one tag per line, multiple words allowed.
</span>
</label>
<br />
<dd id="newTags">
<textarea
id="entered_subjects"
name="subject:lines"
rows="4"
tal:attributes="id string:${fieldName}_keywords;
name string:${fieldName}_keywords:lines;"
tal:define="subject python:[item for item in value if not context.unicodeTestIn(item,allowedKeywords)]"
tal:content="python:'\n'.join(subject)">
A new tag
</textarea>
</dd>
</dl>
<!-- </tal:condition>-->
</tal:define>
</metal:use>
</metal:define>
<div metal:define-macro="search">
<div metal:use-macro="context/widgets/keyword/macros/edit">
</div>
</div>
</body>
</html>
I fear is a know issue of the old Plone 4 keyword widget.
You should probably change the widget.
An add-on like eea.tags should help.
You can also try to use Plone 5 widget from plone.app.widgets, but this probably it's a more complex task (and not without side effects).

Trouble selecting quantity out of drop down in watir

I have never run into an issue with being able to select a value in a drop down, so I'm not sure how this is different. First, here is the HTML I'm working with:
<div class="hn-select-content hn-select-expand" ng-class="{'open-to-left':openToLeft, 'expand-to-left':expandToLeft}" ng-transclude="" style="">
<ul class="qty-discount whiteBackground border border-hn-secondary-lt text-small ng-scope" scroll-lock="">
<li float-container="">
<div class="float-cont">
<ul class="text-small">
<li class="selected ng-isolate-scope HN-Item-Opt-Sel" li="" <="" on-option-select="changeQuantity(val)" value="1" option="1" ng-class="{'HN-Item-Opt-Sel selected':atcData.quantity == 1}" hn-select-option="">
<div class="hn-select-option ng-binding">1</div>
</li>
</ul>
</li>
<li float-container="">
<div class="text-hn-red float-cont">
<div scroller="qty-discount" floater="" style="">
<span> 10% Off </span>
</div>
<div></div>
</div>
<ul class="text-small">
<li class="ng-isolate-scope" li="" <="" on-option-select="changeQuantity(val)" value="2" option="2" ng-class="{'HN-Item-Opt-Sel selected':atcData.quantity == 2}" hn-select-option="">
<div class="hn-select-option ng-binding">2</div>
</li>
I want to select a specific option. in this case, I have a variable set for the quantity, and it's set to 2.
This it the code from the step that is failing:
#browser.div(:id, 'hn_modal_contentIV').div(:text, '1').when_present.click
#browser.ul(:class, 'whiteBackground border border-hn-secondary-lt text-small ng-scope').div(:text, quantity).when_present(5).click
#browser.span(:class, 'redText floatRight marginTopOnly3px').wait_until_present(10)
And this is the error I receive:
Watir::Wait::TimeoutError: timed out after 5 seconds, waiting for {:text=>"2", :tag_name=>"div"} to become present
The drop down box opens, I just can't get the value to be selected.
I have tried a few other variations, but none have worked. Any help would be GREATLY appreciated. Hopefully there is something small that I'm just missing.
Thanks!
First, before this code, HTML must have an select list, perhaps this select list have the attribute "display: none", then you can:
browser.execute_script("document.getElementById('[id of this select list ]').style.display = 'block';")
browser.select(:id => '[id of this select]').option(:text => '[text that you need]').select

Select elements which has certain descendent using Xpath

I want to Select all the LI elements which contain SPAN with id="liveDeal152_dealPrice" as descendents. How do i do this with xpath?
Here is a sample html
<ul>
<li id="liveDeal_152">
<p class="price">
<em>|
<span class="WebRupee">₹ </span>
<span id="liveDeal152_dealPrice">495 </span>
</p>
</li>
<li id="liveDeal_152">
<p class="price">
<em>|
<span class="WebRupee">₹ </span>
(price hidden)
</p>
</li>
</ul>
//li[.//span[#id = 'liveDeal152_dealPrice']] should do. Or more verbose but closer to your textual description //li[descendant::span[#id = 'liveDeal152_dealPrice']].
Use this
//li[.//span[#id="liveDeal152_dealPrice"]]
It selects
ALL <li> ELEMENTS
//li[ ]
THAT HAVE A <span> DESCENDANT
.//span[ ]
WITH id ATTRIBUTE EQUAL TO "liveDeal152_dealPrice"
#id="liveDeal152_dealPrice"
That said, it doesn't seem like a very wise element selection, mostly due to the dynamically looking id. If you're going to use it once, it's probably ok, but if you're using it, say, for testing and will reuse it many times, it might cause trouble. Are you sure this won't change when you change your website and/or database?
As a side note:
ul stands for "unordered list"
ol stands for "ordered list"
li stands for "list item"

Xpath: locate a node by multiple attributes of a parent node

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.

Resources