I got a big XML. A snippet of that XML look like this:
<div class="x-column-inner" id="ext-gen422" style="width: 850px;">
<div id="ext-comp-1206" style="width: 14px;" class=" x-column">
<div tabindex="-1" class="x-form-item x-hide-label" id="ext-gen434">
<label class="x-form-item-label" style="width:100px;" for="ext-comp-1180" id="ext-gen435"></label>
<div style="padding-left:105px" id="x-form-el-ext-comp-1180" class="x-form-element">
<div class="x-form-check-wrap" id="ext-gen436" style="width: 14px; height: 28px;">
<input type="checkbox" name="ext-comp-1180" id="ext-comp-1180" autocomplete="off" class=" x-form-checkbox x-form-field">
<label class="x-form-cb-label" for="ext-comp-1180" id="ext-gen437"> </label>
</div></div> <div class="x-form-clear-left">
</div>
</div>
</div>
<div id="ext-comp-1207" style="width: 150px;" class=" x-column">
<label id="ext-comp-1203" style="width: 140px;">Add to Watchlist</label>
</div>
<div id="ext-comp-1208" style="width: 107px;" class=" x-column">
I need to find ‘input’ node of checkbox type based on label node having text ‘Add to Watchlist’.
As both ‘input’ and ‘label’ node lies in different hierarchy, // syntax doesn’t seem to work:
//div[label[contains(text(),'Add to Watchlist')]]
will just give parent div of child label.
I tried to start from the topmost node of this snippet
$x("//div[@class='x-column-inner' and //label[contains(text(),'Add to Watchlist')]]")
but that is giving 6 possible matches.
Note: @id attribute can’t be used as this is getting assigned dynamically to nodes so next time page loads @id will be different.
I don’t want to use position() predicate as that makes XPATH static and xpath may break with any change in position.
You could try something like this, but it looks very greedy… Basically what it does is searching in every axes of the
inputtags to see if there is an associatedlabeltag. So for eachinputit searches in its ancestors, descendants and siblings.There are certainly some smarter solutions.
However your snippet is not interesting no
inputtag will be matched, please consider providing a better snippet. It would improve the answers accuracy.Edit : Here is a (non-tested) way to add the ‘Add to Watchlist’ constraint.
But once again, those xpath requests are very greedy and your are not guaranteed to match every
inputelement associated to alabelfor example the followinginputwon’t be match in this snippet:There may be more efficient solutions in one xpath request, but you should consider doing several request.
For example, one request to find every
forattribute value of thelabelelements with the text ‘Add to Watchlist’ and then doing another request to find the associatedinputelements.I should also try to restrict your request to the scope a the underlying
formelement. Perhaps I will edit with a better request if I find the time.Edit 2
Here is a working and smarter request
You can confront it to this snippet
Bust the most important is that you understand how it works and why it is better. Please take the time to think about it.