Escape single quote in XPath with Nokogiri?

abhir picture abhir · Feb 11, 2013 · Viewed 22k times · Source

I have an XPath query that looks like this, with both single and double quotes. How do I escape the apostrophe properly so that the query works?

I tried:

"//li[text()='Frank's car']"

but it doesn't seem to do it for me.

Any ideas?

 "//li[text()='Frank's car']"

Answer

matt picture matt · Feb 12, 2013

XPath doesn’t have any way of escaping special characters, so this is a little tricky. A solution in this specific case would be to use double quotes instead of single quotes in the XPath expression:

text()="Frank's car"

If you did this, you’d have to escape the quotes from Ruby if you used double quotes around the whole expression:

"//li[text()=\"Frank's car\"]"

You could use single quotes here if you aren’t doing any interpolation, and then escape the single quote:

'//li[text()="Frank\'s car"]'

A better option would perhaps be to make use of Ruby’s flexible quoting, so that none of the quotes would need escaping ,e.g.:

%{//li[text()="Frank's car"]}

Note that all the examples here doing escaping in Ruby, so that the string that reaches the XPath processor is //li[text()="Frank's car"].

The more general case, when the text is variable that could contain single or double quotes is more difficult. XPath’s string literals can’t contain both types of quotes; you need to construct the string using the XPath concat function.

For example, if you wanted to match the string "That's mine", he said., you would need to do something like:

text()=concat('"That', "'", 's mine", he said.')

And then you’d have to escape the quotes from Ruby (using %{} would be easiest).

I found another question on SO dealing with this issue in C#, and a thread on the Nokogiri mailing list, both of which might be worth looking at if you need to take this further.