WebElement の xpath を返すことは可能ですか?
8 に答える
WebDriver から直接ではありませんが、本当に必要な場合は偽造できます。
public String getElementXPath(WebDriver driver, WebElement element) {
return (String)((JavascriptExecutor)driver).executeScript("gPt=function(c){if(c.id!==''){return'id(\"'+c.id+'\")'}if(c===document.body){return c.tagName}var a=0;var e=c.parentNode.childNodes;for(var b=0;b<e.length;b++){var d=e[b];if(d===c){return gPt(c.parentNode)+'/'+c.tagName+'['+(a+1)+']'}if(d.nodeType===1&&d.tagName===c.tagName){a++}}};return gPt(arguments[0]).toLowerCase();", element);
}
Javascript はこの投稿からのもので、1 行に収まるように縮小されています。完璧ではないかもしれませんが、どこに行くべきかのアイデアを与えることができます. ほとんどのドライバーはJavascriptExecutor
インターフェースを実装し、ブラウザーで Javascript を実行する機能を備えています。executeScript
プリミティブな JavaScript 型、HTML 要素、または前述のいずれかのネストされていないリストを返すことができます。
すべてのブラウザーが同じ方法で xpath をサポートしているわけではないため、これらの xpath を使用して要素を選択する場合は注意してください。また、すべてのブラウザーがネイティブの xpath サポート (咳IE咳) を持っているわけではないため、その場合は偽造されました。
WebElement が By.xpath: によって見つかった場合: Java:
public static String GetWebElementXpath(WebElement El) throws AssertionError{
if ((El instanceof WebElement)){
Object o = El;
String text = o.toString();
/* text is smth like this
[[FirefoxDriver: firefox on WINDOWS (9170d4a5-1554-4018-adac-f3f6385370c0)] -> xpath: //div[contains(@class,'forum-topic-preview')]//div[contains(@class,'small-human')]]
*/
text = text.substring( text.indexOf("xpath: ")+7,text.length()-1);
return text;
}else { Assert.fail("Argument is not an WebElement, his actual class is:"+El.getClass()); }
return "";
}
上記の答えは両方とも同じ問題を抱えています。呼び出された関数で完成した XPath を返すことにより.toLowerCase()
、大文字の ID を含む XPath は機能しなくなります。
例://div[@id="deviceblock-1111"]
タグでは機能しません<div id="deviceBlock-1111">
ただし、戻り値から呼び出しを削除することもでき.toLowerCase()
ますが、XPath は次のようになります。//DIV[@id="deviceBlock-1111"]/DIV[2]/SELECT[1]/OPTION[5]
これを解決するには、以下の関数を使用します。
public String GetElementXPath(WebElement element, WebDriver driver)
{
return (String) ((JavascriptExecutor) driver).executeScript(
"getXPath=function(node)" +
"{" +
"if (node.id !== '')" +
"{" +
"return '//' + node.tagName.toLowerCase() + '[@id=\"' + node.id + '\"]'" +
"}" +
"if (node === document.body)" +
"{" +
"return node.tagName.toLowerCase()" +
"}" +
"var nodeCount = 0;" +
"var childNodes = node.parentNode.childNodes;" +
"for (var i=0; i<childNodes.length; i++)" +
"{" +
"var currentNode = childNodes[i];" +
"if (currentNode === node)" +
"{" +
"return getXPath(node.parentNode) +
'/' + node.tagName.toLowerCase() +
'[' + (nodeCount+1) + ']'" +
"}" +
"if (currentNode.nodeType === 1 && " +
"currentNode.tagName.toLowerCase() === node.tagName.toLowerCase())" +
"{" +
"nodeCount++" +
"}" +
"}" +
"};" +
"return getXPath(arguments[0]);", element);
}
これにより、WebElement から正しくフォーマットされた一意の XPath が返されます。
//div[@id="deviceBlock-1111"]/div[2]/select[1]/option[5]
public String getElementXPath(WebDriver driver, WebElement element) {
String javaScript = "function getElementXPath(elt){" +
"var path = \"\";" +
"for (; elt && elt.nodeType == 1; elt = elt.parentNode){" +
"idx = getElementIdx(elt);" +
"xname = elt.tagName;" +
"if (idx > 1){" +
"xname += \"[\" + idx + \"]\";" +
"}" +
"path = \"/\" + xname + path;" +
"}" +
"return path;" +
"}" +
"function getElementIdx(elt){" +
"var count = 1;" +
"for (var sib = elt.previousSibling; sib ; sib = sib.previousSibling){" +
"if(sib.nodeType == 1 && sib.tagName == elt.tagName){" +
"count++;" +
"}" +
"}" +
"return count;" +
"}" +
"return getElementXPath(arguments[0]).toLowerCase();";
return (String)((JavascriptExecutor)driver).executeScript(javaScript, element);
}
/**
* This method return By reference for the WebElement passed to it as a parameter.
* @param element
* @return
*/
public static By convertWebElementToByReference(WebElement element)
{
By byLocator = null;
String elementDescription = element.toString();
String elementTypeAndValue[] = (elementDescription.substring(elementDescription.lastIndexOf("-> ") + 3, elementDescription.lastIndexOf("]"))).split(":");
switch (elementTypeAndValue[0].trim())
{
case "id": byLocator = By.id(elementTypeAndValue[1].trim());
break;
case "xpath": byLocator = By.xpath(elementTypeAndValue[1].trim());
break;
case "link text": byLocator = By.linkText(elementTypeAndValue[1].trim());
break;
case "tag name": byLocator = By.tagName(elementTypeAndValue[1].trim());
break;
case "class name": byLocator = By.className(elementTypeAndValue[1].trim());
break;
case "partial link text": byLocator = By.partialLinkText(elementTypeAndValue[1].trim());
break;
case "name": byLocator = By.name(elementTypeAndValue[1].trim());
break;
case "css selector": byLocator = By.cssSelector(elementTypeAndValue[1].trim());
break;
default:
throw new RuntimeException("Invalid locator type: " + elementTypeAndValue[0].trim());
}
return byLocator;
}
JavaScript を使用せずに要素 XPath を取得する方法があります。
- body タグなど、外側の XPath の開始点を定義します。
- のセレンで考えられるすべての内側タグを確認してください
NoSuchElementException
。 getText
生成された XPath のリストを確認します。- 勝つ