Вот предположим, что есть у нас такой XPath-локатор:
Всё вроде бы просто - ищет ячейку таблицы в которой есть текст: my simple string. Но что делать если текст, который надо найти содержит одинарные кавычки, вот такой: my 'apos' string? Не беда, можно обрамить его в двойные кавычки в XPath-локаторе вот так:xpath=//td[text()='my simple string']
Всё прекрасно работает. Аналогично если текст содержит двойные кавычки, то обрамляем в одинарные.xpath=//td[text()="my 'apos' string"]
Но что делать если текст содержит как одинарные так и двойные кавычки, например: my 'apos' and "quot" string? Первая мысль - от'escape'ить их обратным слешем, вот так:
И тут мы обнаруживаем, что escape'инг в XPath не работает :( К сожалению это не только в Selenium'е так, так во всём XPath'е.xpath=//td[text()='my \'apos\' and "quot" string']
Как быть?
Можно использовать такое решение:
Т.е. мы всегда используем одинарные кавычки для обрамления, кроме самих одинарных кавычек, которые обрамляем двойными, а потом "склеиваем" строку. Теперь всё прекрасно работает.xpath=//td[text()=concat('my ',"'",'apos',"'",' and "quot" string')]
Можно написать такой вот escape-метод для подобных случаев (Java):
/** * Escapes the characters in a passed string to be suitable to pass to an XPath expression. * <p/> * Because there is no escape character in XPath string values, this method is not really escapes passed string, but * transforms it using a little trick with XPath concatenation function. * <p/> * Algorithm is: <ol><li>If string is <code>null</code>, then <code>null</code> is returns.</li><li>If string * doesn't contains "'" (apostrophe) character, then it returns as is, but quotes with "'" (apostrophe) character. * For example: <code>abcd</code> string will be returned as <code>'abcd'</code>.</li><li>If string contains "'" * (apostrophe) character, then it splits into string tokens and replaces with XPath <code>concat()</code> function. * For example: <code>ab'cd'ef</code> string will be returned as <code>concat('ab',"'",'cd',"'",'ef')</code></li><ol> * * @param string String to escape. * @return Escaped string. */ @Nullable public static String escapeXPath(@Nullable String string) { if (string == null) { return null; } else if (string.contains("'")) { StringBuilder sb = new StringBuilder(); sb.append("concat('"); for (int i = 0; i < string.length(); i++) { char ch = string.charAt(i); if ('\'' == ch) { sb.append("',\"").append(ch).append("\",'"); } else { sb.append(ch); } } sb.append("')"); return sb.toString(); } else { return "'" + string + "'"; } }
Конструктивная критика приветствуется :)