2010-11-14 1 views

ответ

9

не непосредственно из 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 от this post, уменьшенная, чтобы поместиться на одной линии. Это может быть не идеально, но может дать вам представление о том, куда идти. Большинство драйверов реализуют интерфейс JavascriptExecutor и имеют возможность запускать Javascript в браузере. executeScript может возвращать любой примитивный тип JavaScript, элемент HTML или не вложенный список любого из предыдущих.

Not all browsers support xpath the same way, поэтому будьте внимательны, если вы используете эти xpaths для выбора элементов. Кроме того, не все браузеры имеют встроенную поддержку xpath (cough IE cough), поэтому в этом случае он был подделан.

+0

Это awersome :) отлично работает с Chrome 62. Благодарности dflems :) –

1
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);  

} 
+1

сигнатура метода выше не помещался в сером помещении, поэтому следите за тем, чтобы ... – Michael

2

Оба вышеупомянутых ответа страдают от одной и той же проблемы. Вернув завершенный XPath с вызываемой функцией .toLowerCase(), любой 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); 
} 

Это вернет правильно отформатированный уникальный XPath из вашего WebElement.

//div[@id="deviceBlock-1111"]/div[2]/select[1]/option[5]

0

Существует способ, чтобы получить элементы XPath без использования JavaScript.

  1. Определить начальную точку внешнего XPath, например тег тела.
  2. Проверить все возможные входящие теги с селеном на NoSuchElementException.
  3. Отметьте getText для списков генерируемых XPath.
  4. выиграть
4

Если 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 ""; 
    } 
0
public static String getXPathFromElement(WebElement element) { 
     String elementDescription = element.toString(); 
     return elementDescription.substring(elementDescription.lastIndexOf("-> ") + 3, elementDescription.lastIndexOf("]")); 
} 

Web элемент ToString() выглядит следующим образом:

«[[ FirefoxDriver: firefox на WINDOWS (ceb69f9f-bef4-455d-b626-ab439f195be6)] -> id: pageBeanfundDescription] '

Я просто извлекаю id/xpath.

0
/** 
* 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; 
} 
+0

Пожалуйста, добавьте некоторое описание вместе с образцом кода. –

0

Я хотел бы прокомментировать непосредственно на dflems 'answer, но у меня нет репутации, чтобы сделать это.

Преобразование всего xpath в нижний регистр прекрасен, если только xpath не содержит значения id, которые не все в нижнем регистре. Ниже приведен модифицированный вариант Javascript dflems', но в Python вместо Java:

def get_xpath_from_element(driver, element): 
    return driver.execute_script("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.toLowerCase()+'['+(a+1)+']'}if(d.nodeType===1&&d.tagName===c.tagName){a++}}};return gPt(arguments[0]);", element) 

 Смежные вопросы

  • Нет связанных вопросов^_^