web-dev-qa-db-ja.com

テキストで要素を見つけてxpathを取得する-Selenium webdriver junit

Webページに9行6列のテーブルがあります。 「MakeGoodDisabled-Programwise_09_44_38_461(n)」というテキストを検索して、セルのxpathを取得します。以下を使用しましたが、ページ上のテキストを見つけることができないため失敗します。助けてもらえますか?私はこれをコーディングするためにSelenium Webdriver Junitを使用しています。

List < WebElement > links = driver.findElements(By.tagName("td"));

Iterator < WebElement > itr = links.iterator();
while (itr.hasNext()) {
 String test = itr.next().getText();

 if (test.equals("MakeGoodDisabled-Programwise_09_44_38_461(n)")) {
  String xpath = driver.findElement(By.name(test)).getAttribute("xpath");
  System.out.println(xpath);
 }
}
10
Nandini Joshi

私の意図は、テーブル内のテキストを検索し、同じ行で対応する次の列の値を取得することです。 xpathをフェッチして見つかった列番号を、必要な列番号に置き換えると思いました。それを行うより良い方法はありますか

もちろん、方法があります。考えられる解決策の1つを次に示します。

すべての行を取得します。

While (iterate over row)
     While(Iterate over column)
           if(column.Text=='YOUR_MATCH'){
             int voila=column.Index
           }
    }
}

これで、他の行の特定のインデックスに簡単に移動できます。または、.../tr/td[voila]などのxpathを使用して、その特定の列のすべてのセルを取得できます。

アプローチを作成しました。実際に動作するコードであるとは思わないでください!

0
coding_idiot

これを使用して、xpathをクロールして生成することもできます。

以下のメソッドを呼び出します

generateXPATH(element, "");

出力は次のようになります。

/html[1]/body[1]/div[5]/div[1]/div[2]/div[1]/div[1]/div[1]/div[1]/div[1]/div[1]/form[1]/div[2]/div[1]/input[2]

方法

private String generateXPATH(WebElement childElement, String current) {
    String childTag = childElement.getTagName();
    if(childTag.equals("html")) {
        return "/html[1]"+current;
    }
    WebElement parentElement = childElement.findElement(By.xpath("..")); 
    List<WebElement> childrenElements = parentElement.findElements(By.xpath("*"));
    int count = 0;
    for(int i=0;i<childrenElements.size(); i++) {
        WebElement childrenElement = childrenElements.get(i);
        String childrenElementTag = childrenElement.getTagName();
        if(childTag.equals(childrenElementTag)) {
            count++;
        }
        if(childElement.equals(childrenElement)) {
            return generateXPATH(parentElement, "/" + childTag + "[" + count + "]"+current);
        }
    }
    return null;
}
24
Scott Izu

あなたが尋ねた質問は私には意味がありません。 「やりたい」という強い理由があるのではないでしょうか。

コードの行

 String xpath = driver.findElement(By.name(test)).getAttribute("xpath");

html要素には属性「xpath」がないため、何も返されません。 xpathの意味を理解してください。

以下に示すようなhtml要素がある場合

<input name = "username" value = "Name" readonly ="readonly">

を使用して属性の値を取得できます

driver.findElement(By.name("username").getAttribute("value");  // returns 'Name'

これにより、「value」属性の値が得られます

または

driver.findElement(By.name("username").getAttribute("readonly");  // returns 'readonly'

同上 !

7
Abhishek Singh

要素のXPathは決定的な値ではありません。要素は多くのXPathで見つけることができます。

Webdriverを使用してXPathを抽出することはできません。可能な場合でも、それが最も効率的または賢明なものである可能性は低く、オートマトンによってのみ定義できます。

5
Robbie Wareham

XPathを生成するJavaScript機能

XPath /locatorは、ツリー構造をナビゲートして要素をアドレス指定する方法です。

絶対XPath(/):/ html/body/div [5]/div [4]

WebElement XPath:

function WebElement_XPath(element) {
    if (element.tagName == 'HTML')    return '/html';
    if (element===document.body)      return '/html/body';

    // calculate position among siblings
    var position = 0;
    // Gets all siblings of that element.
    var siblings = element.parentNode.childNodes;
    for (var i = 0; i < siblings.length; i++) {
        var sibling = siblings[i];
        // Check Siblink with our element if match then recursively call for its parent element.
        if (sibling === element)  return WebElement_XPath(element.parentNode)+'/'+element.tagName+'['+(position+1)+']';

       // if it is a siblink & element-node then only increments position. 
        var type = sibling.nodeType;
        if (type === 1 && sibling.tagName === element.tagName)            position++;
    }
}

MouseEvent XPath:

var eventXPath = '';
function MouseEvent_XPath(e) {      
    event = e.target || e.srcElement ||e.originalTarget;

    for ( var xpathEle = ''; event && event.nodeType == 1; event = event.parentNode ) {
        if ( event.tagName == 'HTML' || event.tagName == 'html' ) {
            eventXPath = '//html'+xpathEle;         break;
        }     
        if ( event.tagName == 'BODY' || event.tagName == 'body' ) {
            eventXPath = '//html/body'+xpathEle;    break;
        }     

        // calculate position among siblings
        var position = 0;
        // Gets all siblings of that event.
        var siblings = event.parentNode.children;
        for (var i = 0; i < siblings.length; i++) {
            var sibling = siblings[i];
        // Check Sibling with our event if match then recursively call for its parent event.
            if (sibling === event)  xpathEle = "/"+event.tagName+'['+(position+1)+']'+xpathEle;

           // if it is a sibling with same tagName then only increments position. 
            if (sibling.tagName === event.tagName)            position++;
        }
    }
}

相対xpath(//):// div [@ id = 'social-media']/ul/li [ 3]/a

// Element.TagName [@ id = "idvalue" and @ class = "classValue" and text()= "innerHTML data"]ORあなた。(dot)、を使用できます。は、text()のエイリアスです。[。= "innerHTML data"]探しているコンテンツが指定されたタグ内にあることがわかっている場合は、thisを使用できます

コンソールでの実行例:

var xpath  = "//div[@id='answer-32201731' and @data-answerid='32201731']";
var element = document.evaluate(xpath, window.document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null ).singleNodeValue;
element.style.setProperty( 'outline', "3px solid blue","important");
1
Yash

My Java絶対xpathを取得するメソッド:

public static String getXpath(WebElement element){
    int n = element.findElements(By.xpath("./ancestor::*")).size();
    String path = "";
    WebElement current = element;
    for(int i = n; i > 0; i--){
        String tag = current.getTagName();
        int lvl = current.findElements(By.xpath("./preceding-sibling::" + tag)).size() + 1;
        path = String.format("/%s[%d]%s", tag, lvl, path);
        current = current.findElement(By.xpath("./parent::*"));
    }
    return "/" + current.getTagName() + path;
}

相対xpathの場合(これが最初でした:)):

public static String getXpath(WebElement self, WebElement ancestor){
    int a = ancestor.findElements(By.xpath("./ancestor::*")).size();
    int s = self.findElements(By.xpath("./ancestor::*")).size();
    String path = "";
    WebElement current = self;
    for(int i = s - a; i > 0; i--){
        String tag = current.getTagName();
        int lvl = current.findElements(By.xpath("./preceding-sibling::" + tag)).size() + 1;
        path = String.format("/%s[%d]%s", tag, lvl, path);
        current = current.findElement(By.xpath("./parent::*"));
    }
    return path;
}
1
Adam Silenko

JavaScriptでxpathを生成できます:

function getPathTo(element) {

    // only generate xpaths for elements which contain a particular text:
    if (element.innerText == "MakeGoodDisabled-Programwise_09_44_38_461(n)") {

        // use id to produce relative paths rather than absolute, whenever possible
        if ((element.id !== '') && (element.id != 'undefined')) {
            return 'id(\"' + element.id + '\")';
        }

        // stop looping when you get to the body tag
        if (element === document.body) {
            return element.tagName;
        }

        // calculate position among siblings
        var ix = 0; 
        var siblings = element.parentNode.childNodes;
        for (var i = 0; i < siblings.length; i++) {
            var sibling = siblings[i];
            if (sibling === element) {
                return getPathTo(element.parentNode) + '/' + element.tagName + '[' + (ix + 1) + ']';
            }
            if (sibling.nodeType === 1 && sibling.tagName === element.tagName) {
                ix++;
            }
        }
    }
}

// put all matching xpaths in an array
var allXPaths = []; 

// if you know the particular tag you are looking for, replace * below to optimize 
var allTags = document.getElementsByTagName('*');
for (i = 0; i < allTags.length; i++) {
    if ((getPathTo(allTags[i]).indexOf('/HEAD') == -1) && (getPathTo(allTags[i]).indexOf('undefined') == -1)) {
        allXPaths.Push(getPathTo(allTags[i]));
        console.log(getPathTo(allTags[i]));
    }
}
return allXPaths;

そのJavaScriptをgetXPathsと呼ばれる文字列に入れ、次にJavaに入れると、次のように実行できます。

ArrayList<String> xpaths = (ArrayList<String>) js.executeScript(getXPaths);

一致するtagname/innerTextのある要素の数が少ないか多い場合、知りたいと思うので、文字列ではなく配列を返します。配列のサイズで判断できます。

1
Dingredient

要素に「xpath」という名前の属性があると仮定すると、次のことができます。

WebElement yourElement = driver.findElement(By.xpath("//td[contains(text(),'MakeGoodDisabled-Programwise_09_44_38_461(n)')]");
String xpathAttributeValue = targetButton.getAttribute("xpath");

それの音によって、あなたはここで何か他のものを達成しようとしていますが、まだ私たちと共有していません。 Seleniumでxpathを作成しますか?できません。

0
joostschouten

私とほぼ同じ状況:

テーブルに要素がありますが、それがどの列にあるかわかりません(すべてのユーザー名にわたるユーザー名など)。ユーザー名を持つ特定の文字列を見つけて、このユーザー専用の「アクティブ化」ボタンをクリックする必要があります。 (ユーザー名テキストはtd [2]である2番目の列にあり、ボタンはtd [5]である5番目の列にあります)。そのため、すべての列を1つずつ実行してユーザーを見つけ、そのボタンをクリックする必要があります。

for (int iter = 1;; iter++) {
                try {
                    if (iter == 1) {
                            if ((username).equals(driver.findElement(By.xpath("/html/body/div[3]/div[4]/div/form/table/tbody/tr/td[2]/a")).getText())) {
                                driver.findElement(By.xpath("/html/body/div[3]/div[4]/div/form/table/tbody/tr/td[5]/a")).click();
                                break;
                            }
                    }
                } catch (Error e) {}
                try {
                    if (iter > 1) {
                            if ((username).equals(driver.findElement(By.xpath("/html/body/div[3]/div[4]/div/form/table/tbody/tr[" + iter + "]/td[2]/a")).getText())) {
                                driver.findElement(By.xpath("/html/body/div[3]/div[4]/div/form/table/tbody/tr[" + iter + "]/td[5]/a")).click();
                                break;
                            }
                        }
                    } catch (Error e) {}
                } 
          }
0
dred17

反復する前に、このクラスを使用します。次に、XPATHIDFromWebElementを見つけたら

import Java.util.LinkedHashMap;
import Java.util.List;
import Java.util.Map;
import org.openqa.Selenium.By;
import org.openqa.Selenium.WebDriver;
import org.openqa.Selenium.WebElement;

public class XPATHDriverWrapper {
Map xpathIDToWebElementMap = new LinkedHashMap();
Map webElementToXPATHIDMap = new LinkedHashMap();
public XPATHDriverWrapper(WebDriver driver){
    WebElement htmlElement = driver.findElement(By.xpath("/html"));
    iterateThroughChildren(htmlElement, "/html");
}

private void iterateThroughChildren(WebElement parentElement, String parentXPATH) {
    Map siblingCountMap = new LinkedHashMap();

    List childrenElements = parentElement.findElements(By.xpath(parentXPATH+"/*"));
    for(int i=0;i<childrenElements.size(); i++) {
        WebElement childElement = childrenElements.get(i);
        String childTag = childElement.getTagName();
        String childXPATH = constructXPATH(parentXPATH, siblingCountMap, childTag);
        xpathIDToWebElementMap.put(childXPATH, childElement);
        webElementToXPATHIDMap.put(childElement, childXPATH);
        iterateThroughChildren(childElement, childXPATH);
//          System.out.println("childXPATH:"+childXPATH);
    }
}

public WebElement findWebElementFromXPATHID(String xpathID) {
    return xpathIDToWebElementMap.get(xpathID);
}

public String findXPATHIDFromWebElement(WebElement webElement) {
    return webElementToXPATHIDMap.get(webElement);
}

private String constructXPATH(String parentXPATH,
        Map siblingCountMap, String childTag) {
    Integer count = siblingCountMap.get(childTag);
    if(count == null) {
        count = 1;
    } else {
        count = count + 1;
    }
    siblingCountMap.put(childTag, count);
    String childXPATH = parentXPATH + "/" + childTag + "[" + count + "]";
    return childXPATH;
}
}

DocumentからIDを生成する別のラッパークラスが投稿されます: http://scottizu.wordpress.com/2014/05/12/generated-unique-ids-for-webelements-via-xpath/

0
Scott Izu

検索された要素のxpathを取得するために利用できる特別な関数はありません。そのためには、まず要素を手動で見つけてから、getXpath関数を使用してxpathを取得する必要があります。

0
Atif Hussain