12

I have a node as follows:

<span class="portal-text-medium">Office Hours</span>

For the XPath I use

//span[text()='Office Hours']

which should work, but it never does. I can use *contains(text(),'Office Hours')]* but that won't find an exact match and I have to verify there is no "*". This is not the only time it hasn't worked for me. I have seen it work before so I don't know what is wrong. Any idea?

Yes I can, and do, use starts-with but it is not quite the same.

kjhughes
  • 89,675
  • 16
  • 141
  • 199
Tony
  • 317
  • 4
  • 16
  • I have the page open in Chrome, and I do an inspect and then ctrl-f which opens a box in the lower left corner into which I can type xpaths. If the xpath matches, then the number of matches is shown and the first one is highlighted in yellow. Actually even if no match is found the number of matches is shown, and is shown as 0. When I use this xpath 0 matches are shown. When I use contains() or starts-with(), 14 or so matches are shown. – Tony Jan 04 '16 at 15:03

2 Answers2

44

XPath text() = is different than XPath . =

(Matching text nodes is different than matching string values)

The following XPaths are not the same...

  1. //span[text() = 'Office Hours']

    Says:

    Select the span elements that have an immediate child text node equal to 'Office Hours`.

  2. //span[. = 'Office Hours']

    Says:

    Select the span elements whose string value is equal to 'Office Hours`.

In short, for element nodes:

The string-value of an element node is the concatenation of the string-values of all text node descendants of the element node in document order.

Examples

The following span elements would match only #1:

  • <span class="portal-text-medium">Office Hours<br/>8:00-10:00</span>
  • <span class="portal-text-medium">My<br/>Office Hours</span>

The following span elements would match only #2:

  • <span class="portal-text-medium"><b>Office</b> Hours</span>
  • <span class="portal-text-medium"><b><i>Office Hours</i></b></span>

The following span element would match both #1 and #2:

  • <span class="portal-text-medium">Office Hours</span>
kjhughes
  • 89,675
  • 16
  • 141
  • 199
  • So for using a ".", parts of the string can be at different depths, as long as when appended together it comes out to the value you are searching? I think sometimes when I encountered that problem I should have tried I should have used a . because maybe there were some extra levels I did not know about. – Tony Jan 04 '16 at 17:02
  • You got it. More precisely per the XPath recommendation: *The string-value of an element node is the concatenation of the string-values of all text node descendants of the element node in document order.* Answer updated. Thanks. – kjhughes Jan 04 '16 at 17:09
0

Use contains with AND operation, which will help you to find the exact element

//span[contains(@class, 'portal-text-medium') and text()='Office Hours']
Vinayak Shedgeri
  • 1,746
  • 19
  • 23