简体   繁体   中英

Using Xpath Contains function to find element that contains text

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 &amp;&amp; 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 &amp;&amp; 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">
                -->

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')]

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)']

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM