Reputation: 233
I have been using the Contains function for my selenium Xpath locators. Up until now, this function always worked. It currently does NOT work for a TD element in a table. I am sending the correct text to the function, so I dont understand why.
On Chrome, go to here: https://rcpsc.releasecandidate-community360qa.net/login.aspx?action=enablelogin
Login with: mj4/test
Scroll down to the Program Learning Plan tab
Object Inspect the row which says "Transition to Discipline (4)". You will see that this element is a TD element with innerText of "Transition to Discipline".
Now press Ctrl+F in the Elements tab of developer tools to Find by string, selector, or Xpath. Type the following to try to find by Xpath: //td[contains(text(),'Discipline')] It does not find the element. Why is this?
Now type in //*[contains(text(),'Discipline')] It finds a DIV element with this text, but this is not the element I want/need.
How can I find the td element. Note that I need to find this element by using the text.
Here is my code to find the element:
string xpath = string.Format("//td[contains(text(),'{0}')]", "Discipline");
IWebElement elemToExpandOrCollapse = PrgLrnPlanTbl.FindElement(By.XPath(xpath));
Here is the HTML:
<tbody ng-repeat="stage in vm.Stages.PortfolioEPAStages" class="ng-scope">
<tr>
<td class="text-left ng-binding" colspan="2">
<!-- ngIf: stage.EPACount --><span ng-if="stage.EPACount" class="ng-scope"><span role="button" ng-hide="vm.isStageExpand==true && stage.StageId==vm.selectedStageId" ng-click="vm.toggleStages(stage.StageId)" tabindex="0" cbd-enter="" first-tab="" class="ng-hide"><img class="" src="/cbd/Content/images/icons/icon.expand.png" alt="Expand"></span> <span role="button" ng-show="vm.isStageExpand==true && stage.StageId==vm.selectedStageId" ng-click="vm.toggleStages()" tabindex="0" cbd-enter="" first-tab="" class=""><img class="" src="/cbd/Content/images/icons/icon.collapse.png" alt="Collapse"> </span> </span><!-- end ngIf: stage.EPACount --><!-- ngIf: stage.EPACount <=0 -->Transition to Discipline (4)
</td>
</tr>
<!-- ngIf: stage.StageId==vm.selectedStageId --><tr ng-if="stage.StageId==vm.selectedStageId" class="ng-scope">
<!-- ngIf: stage.EPACount>0 --><td colspan="2" ng-if="stage.EPACount>0" style="padding:0px;" class="ng-scope">
<!--<div class=" row">
<div class="col-md-12">
-->
Upvotes: 1
Views: 3357
Reputation: 139
Please try this:
//td[@class='text-left ng-binding' and ./span[contains(.,'Discipline')]]
OR
//td[@class='text-left ng-binding' and ./span/text()='Transition to Discipline (4)']
Upvotes: 0
Reputation: 163625
Your XPath doesn't work because the string "Discipline" does not occur in the first text node child of the td element, but in a subsequent text node. You are using an XPath 1.0 processor (heaven only knows why Selenium doesn't move to something more modern), and in XPath 1.0 the rule is that contains(X, Y), when X is a set of nodes, only considers the first node in that set, and ignores the others.
I would have thought the closest fit to your stated requirement is something like //td[contains(., 'Discipline')]
Upvotes: 1