0

This was the html code earlier for label 'Home Page' which style attribute

<label style="background: rgb(204, 136, 136); border: 2px solid red;">
<i class="fa fa-info-circle info"></i> Home Page</label>

I had written this XPath earlier which worked well

//*[contains(text(),'Home Page')]

Now I noticed html is changed for label Home Page, style attribute is removed from label as shown below

<label>
<i class="fa fa-info-circle info"></i> Home Page</label>

Because of this changes my existing XPath is not working now, but when I change XPath as shown below, it works

//label[contains(.,'Home Page')]//removed * with label, text() with dot(.)

Also when I use the previous XPath in XPath checker with * none of element is selected now but when I use second XPath with label it select the Home Page label I want.

I think both XPath should have worked, addition or removal of style attribute in label should not have any impact. Can anyone please explain why it is happening so, why my first XPath is not working now, does addition or removal of style attribute in html impact on existing XPath?

Please check the attached screenshot to view the html structure enter image description here

Community
  • 1
  • 1
Shoaib Akhtar
  • 1,393
  • 5
  • 17
  • 46
  • Possible duplicate of [XPath contains(text(),'some string') doesn't work when used with node with more than one Text subnode](https://stackoverflow.com/questions/3655549/xpath-containstext-some-string-doesnt-work-when-used-with-node-with-more) – Florent B. Nov 24 '17 at 06:24
  • It's hard to say without inspecting the whole HTML page. Html was changed by some javasript code fired by some action. Could be that some another element with text `Home page` appeared in the html, and this xpath `//*[contains(text(),'Home Page')]` stopped working, because there were more that 1 elements selected by this xpath - in such a case Selenium reports that the element cannot be found. But it's just a guess. – krokodilko Nov 24 '17 at 06:26
  • @krokodilko As I mentioned in my question itself when I typed this XPath //*[contains(text(),'Home Page')] in XPath checker or Firepath it does not return any element now – Shoaib Akhtar Nov 24 '17 at 06:32
  • Use this XPath to search an element by text : `//*[text()[normalize-space()]][normalize-space()='Home page']`. It is less expensive than `//*[.='Home page']` since it skips the containers without text nodes and it normalize white spaces. – Florent B. Nov 24 '17 at 06:48
  • @FlorentB. Actually I wanted to know how addition or removal of style attribute in label html tag impact on XPath. Since after removal of style attribute from label tag, my first XPath is not working. If I add style attribute then first XPath starts working – Shoaib Akhtar Nov 24 '17 at 08:41
  • @Shoaib Akhtar, I don't get anything with both of your examples The difference is likely due to a line break present in one but not in the other. Bottom line is, `contains` evaluates only the first text node. – Florent B. Nov 24 '17 at 08:51
  • @FlorentB. I have added screenshot of html structure now in question where both looks same apart from removal of style tag. Since developer has removed such style tag from html, most of my XPath related to it are failing. Hence wanted to know does style has impact on XPath – Shoaib Akhtar Nov 24 '17 at 09:14
  • @Shoaib Akhtar, no the style has no impact. Check the page source to see the differences. – Florent B. Nov 24 '17 at 09:22

1 Answers1

1

It's impossible to give the definite answer without seeing the whole HTML document, but probably you have the following problem:

Your initial XPath expression was:

//*[contains(text(),'Home Page')]

Which, in plain English, means:

Select element nodes with any name, if they have at least one text node as a child, and if the first text node in them contains the string "Home Page".

I am emphasizing first because it it not obvious to many that a function like contains() will use only the first node in a sequence, and silently ignore the rest - this is only true for XPath 1.0.

The expression text() does not return a single node, it returns a sequence of nodes if an element has more than one child text node. This happens if there are interfering child element nodes, for example.


There are several ways to confirm this yourself. On the one hand, you can modify the expression to

//*[contains(text()[2], "Home Page")]

which explicitly selects the second text node as the argument for contains() and you will find this label element as a result.

Or, evaluating an expression on only the HTML snippet you show,

/label/text()

will return (individual results separated by ---):

[result that only has whitespace]
-----------------------
 Home Page

which indicates that the i element as a child of label leads to an additional text node in front of i that only has whitespace in it.


A good solution to your problem with the correct semantics is

//*[text()[contains(.,'Home Page')]]

it means:

Select element nodes with any name, if they have at least one text node as a child, and if any text node in them contains the string "Home Page".

Mathias Müller
  • 22,203
  • 13
  • 58
  • 75
  • I have added screenshot of html structure in my question. Please have a look once. Not able to understand why after removal of style attribute from label tag, my first XPath is not working. If I add style attribute then first XPath starts working. Since developer has done similar changes for most of element, most of my XPath is not working – Shoaib Akhtar Nov 24 '17 at 09:18
  • @ShoaibAkhtar We cannot work with a screenshot, and also it is still only a small snippet, not a self-contained, entire HTML document. The presence or absence of an XML attribute has nothing to do with your problem. What you report is consistent with the answer I have given. Did you read my answer? – Mathias Müller Nov 24 '17 at 11:34
  • @ShoaibAkhtar: Adding styles that don't change content won't affect content-only XPath selection. Without a [mcve] that definitively shows otherwise, we can only conclude that you do not understand the concepts that Mathias has adeptly described here. Work on understanding what he's written or on creating a MCVE that disproves his hypothesis, which is by far the most likely explanation of what you're seeing. – kjhughes Mar 24 '18 at 12:05