Escaping XPath literal with Python

2024/10/8 6:26:34

I'm writing a common library to setup an automation test suite with Selenium 2.0 Python's webdriver.

def verify_error_message_present(self, message):try:self.driver.find_element_by_xpath("//span[@class='error'][contains(.,'%s')]" % message)self.assertTrue(True, "Found an error message containing %s" % messageexcept Exception, e:self.logger.exception(e)

I would like to escape the message before passing it to XPath query, so it can support if 'message' is something like "The number of memory slots used (32) exceeds the number of memory slots that are available (16)"

Without escaping, the xpath query won't work since it contains '(' and ')'

Which library can we use to do this in Python?

I know that this is a simple question, but I don't have so much experience in Python (just started).

Thanks in advance.

Additional info:

During testing in firebug, the query below will return no result:

//span[@class='error'][contains(.,'The number of memory slots used (32) exceeds the number of memory slots that are available (16)')]

While the query below will return the desired component:

//span[@class='error'][contains(.,'The number of memory slots used \(32\) exceeds the number of memory slots that are available \(16\)')]

Logically this problem can be solved by replacing ) with \) for this particular string literal, but then there are still the other characters need to be escaped. So is there any library to do this in a proper way?

Answer

Parentheses should be fine there. They're inside an XPath string literal delimited by apostrophe, so they do not prematurely end the contains condition.

The problem is what happens when you have apostrophes in your string, since those do end the string literal, breaking the expression. Unfortunately there is no string escaping scheme for XPath string literals, so you have to work around it using expressions to generate the troublesome characters, typically in the form concat('str1', "'", 'str2').

Here's a Python function to do that:

def toXPathStringLiteral(s):if "'" not in s: return "'%s'" % sif '"' not in s: return '"%s"' % sreturn "concat('%s')" % s.replace("'", "',\"'\",'")"//span[@class='error'][contains(.,%s)]" % toXPathStringLiteral(message)
https://en.xdnf.cn/q/70149.html

Related Q&A

How to return two values in cython cdef without gil (nogil)

I have a function and I am trying to return a number and a vector of ints. What I have is cdef func() nogil:cdef vector[int] vectcdef int a_number...return a_number, vectbut this will give errors like …

Alias for a chain of commands

I have a tool with commands: step1, step2 and step3.I can chain them by calling:$ tool step1 step2 step3I would like to have an alias named all to run all the steps by calling:$ tool allI have found a …

Generate misspelled words (typos)

I have implemented a fuzzy matching algorithm and I would like to evaluate its recall using some sample queries with test data. Lets say I have a document containing the text:{"text": "T…

Get the inverse function of a polyfit in numpy

I have fit a second order polynomial to a number of x/y points in the following way:poly = np.polyfit(x, y, 2)How can I invert this function in python, to get the two x-values corresponding to a speci…

Installing an old version of scikit-learn

Problem StatmentIm trying to run some old python code that requires scikit-learn 18.0 but the current version I have installed is 0.22 and so Im getting a warning/invalid data when I run the code.What …

remove characters from pandas column

Im trying to simply remove the ( and ) from the beginning and end of the pandas column series. This is my best guess so far but it just returns empty strings with () intact. postings[location].replace(…

numerically stable inverse of a 2x2 matrix

In a numerical solver I am working on in C, I need to invert a 2x2 matrix and it then gets multiplied on the right side by another matrix:C = B . inv(A)I have been using the following definition of an …

Type annotating class variable: in init or body?

Lets consider the two following syntax variations:class Foo:x: intdef __init__(self, an_int: int):self.x = an_intAndclass Foo:def __init__(self, an_int: int):self.x = an_intApparently the following cod…

decoding shift-jis: illegal multibyte sequence

Im trying to decode a shift-jis encoded string, like this:string.decode(shift-jis).encode(utf-8)to be able to view it in my program.When I come across 2 shift-jis characters, in hex "0x87 0x54&quo…

Add columns in pandas dataframe dynamically

I have following code to load dataframe import pandas as pdufo = pd.read_csv(csv_path) print(ufo.loc[[0,1,2] , :])which gives following output, see the structure of the csvCity Colors Reported Shape Re…