最近、Webページのオートパイロットやオートパイロットでのテストで何かとお世話になっているSelenium + Junitの環境で ' (シングルクオート)を含んだ文字列を探そうとしたら思いっきり嵌ったのでメモ
Seleniumなどでエレメントを特定する際に ' (シングルクオート)が含まれている文字列を検索したい場合には ' (シングルクオート)をエスケープしなければなりませんが、残念なことにXpath 1.0の仕様では ' (シングルクオート)をエスケープする方法が用意されていませんでした。
XPath 2.0からは、例えば ' (シングルクオート)で囲われた文字列中の ' (シングルクオート)をエスケープするには ' (シングルクオート)を2個続けて書いて '' の様にエスケープするらしいのですが、Firefoxの最新版やChromeでも未だXPath 2.0は使えないらしいです。
で、結局どうしたか?というと以下の様になりました。
例えば、以下の様な文字列が含まれたエレメントをXPathで探す場合には、
<a aria-label="アプリ May'n ちゃん "Love" <1>" href="#MarketListingPlace:p=tmp.03831173739257532153.1317485953465" data-column="TITLE"><img src="gwt/placeholder_icon_24.png" role="presentation"><div> <div>May'n ちゃん "Love" <1></div> <div></div> </div> </a>
以下の様にします (Firefox quantamのconsoleで検索する場合)
$x("//a[@aria-label=concat('アプリ May', \"'\", 'n ちゃん \"Love\" <1>')]")
Selenium + Junitなら以下の様な感じで
Selenium + JunitのBy.xpathで検索
searchString = "アプリ May'n ちゃん \"Love\" <1>";
xPathStringLiteral = toXPathStringLiteral(searchString);
searchXpath = "//a[@aria-label=" + xPathStringLiteral + "]";
wait.until(ExpectedConditions.elementToBeClickable(By.xpath(searchXpath))
toXPathStringLiteral
private String toXPathStringLiteral(String string) {
if ( string.indexOf("'") == -1 ) {
return "'" + string + "'";
}
if ( string.indexOf('"') == -1 ) {
return '"' + string + '"';
}
return ("concat('" + string.replace("'", "', \"'\", '") + "')");
}
…と恐ろしく面倒でした