7

I have the following code line used in selenium python script:

from selenium import webdriver

driver.find_element_by_xpath(u"//span[text()='" + cat2 + "']").click()

cat2 is variable from a database list that i get like this:

db = Database()
sql = "SELECT * FROM missing
listeproduit = db.select(sql)
for record in listeproduit:
    cat2       = record[6]

The probleme is when the variable contain a text like this:

cat2 = Debimetre d'air

Then the script don't works because it's an illegal xpath expression.

From my search, i understand that it's a problem with escaping the single quote in my variable cat2

From this answers :Escape single quote in XPath with Nokogiri?

They suggest to use concat() xpath function, but how to use it in my case ? Thanks for your help.

Cheers

Community
  • 1
  • 1
Andronaute
  • 379
  • 3
  • 12

2 Answers2

9

In XPath 1.0, which is used by browsers and therefore by Selenium, there is no native way of escaping string literals (which was remedied in XPath 2.0). A few workarounds are mentioned by this poster, which includes:

  • First off, make sure you understand the difference between escaping in Python, which is possible, and escaping within the XPath expression
  • Then, if you simply need a single quote, surround it by double quotes, and vice versa
  • Then, if one string literal contains both double and single quotes, use something like concat('"', "Here's Johnny", '"', ", said Johnny."), which combines to the literal: "Here's Johnny", said Johnny..

In your case, this would work:

driver.find_element_by_xpath(u"//span[text()=\"" + cat2 + "\"]").click()

Another way around this is to set an XPath variable to contain the value of your string literal, which helps in readability. But I couldn't find how to do it with the web drivers for Selenium, which typically means there is no such method available.

Community
  • 1
  • 1
Abel
  • 56,041
  • 24
  • 146
  • 247
5

Here is a Python function I've just wrote that escapes a string to use in an XPath 1.0 expression, using the trick described in @Abel's answer:

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

Note that it adds the appropriate kind of quotes around your string, so be sure not to add extra quotes around the return value.

Usage example:

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
Elias Dorneles
  • 22,556
  • 11
  • 85
  • 107