0

I have some Python/Selenium code that finds an element with the specified title text using XPath:

tab_element = WebDriverWait(driver, 10).until(lambda x: x.find_element_by_xpath('//a[@title="' + tab_title + '"]'))

It works fine in most cases, but it fails when it encounters an element with a title that contains double quotes.

<p title="that'll be the &quot;dayg&quot;">That'll be the "day"</p>

So, that leaves me with two questions:

  1. How can I make it work with title values that contain double quotes?

  2. How can I make it work with any title value, such as ones that contain both double and single quotes?

Pikamander2
  • 7,332
  • 3
  • 48
  • 69
  • As pointed by Michael Key, this should work for both single and double quotes :`//p[contains(@title,concat('"',''))]|//p[contains(@title,"'")]`. First part is for double, second for single. – E.Wiest Mar 10 '20 at 11:20

2 Answers2

0

I ended up using Elias's XPath escaping function from this thread.

def escape_string_for_xpath(s):
    if '"' in s and "'" in s:
        return 'concat(%s)' % ", '\"',".join('"%s"' % x for x in s.split('"'))
    elif '"' in s:
        return "'%s'" % s
    return '"%s"' % s

escaped_title = escape_string_for_xpath('"that\'ll be the "day"')

driver.find_element_by_xpath('//a[@title=' + escaped_title + ']')
Pikamander2
  • 7,332
  • 3
  • 48
  • 69
0

For XPath 1.0 the rule is:

(a) a string literal can't contain the mark used as the string delimiter; the only way around that is to form the string using concat(), for example concat("'", '"', "'") is the string of three characters '"'.

(b) if a string literal contains a character that has special meaning in the host language (e.g. " in Java or & in XML) then it needs to be escaped using the host language escaping conventions (\" in Java, &amp; in XML).

In XPath 2.0 you can get around (a) by doubling: for example """" is a string literal representing a string of length one containing a double-quotes character. You can also get around both (a) and (b) by using the codepoints-to-string() function.

Michael Kay
  • 156,231
  • 11
  • 92
  • 164