2013-08-29 8 views
8

У меня есть таблица с 9 строками и 6 столбцами на моей веб-странице. Я хочу найти текст «MakeGoodDisabled-Programwise_09_44_38_461 (n)» и получить xpath ячейки. Я использовал следующее, но он терпит неудачу, потому что он не может найти текст на странице. Не могли бы вы помочь? Я использую Selenium Webdriver Junit для кодирования этого.Найти элемент по тексту и получить 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); 
         } 
        }` 
+2

Что вы пытаетесь сделать? –

+0

подход к решению проблемы в руке неверен! Не могли бы вы обсудить эту проблему, мы предоставим вам хороший подход к тому, как действовать дальше (не ждите много кода, быстрый Google дает много)! –

ответ

0

Мое намерение состоит в том, чтобы найти текст в таблице и получить соответствующее значение следующего столбца в той же строки. Я думал, что я заменил номер столбца, найденный, извлекая xpath с номер столбца, который я хочу.есть ли лучший способ сделать это

Конечно, есть способ. Вот одно из возможных решений.

Получить все строки:

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

Теперь вы можете просто перейти к определенному индексу для других строк; или вы можете использовать xpath как .../tr/td[voila] для извлечения всех ячеек для этого конкретного столбца.

Я написал подход, пожалуйста, не принимайте за действительный рабочий код!

6

XPath элемента не является окончательным значением. Элемент может быть найден многими XPath.

Вы не можете использовать Webdriver для извлечения XPath, и даже если бы это было возможно, оно вряд ли будет самым эффективным или разумным, которое может быть определено только автору.

+0

ОК. Мое намерение состоит в том, чтобы найти текст в таблице и получить соответствующее значение следующего столбца в той же строке. Я думал, что я заменил номер столбца, найденный, извлекая xpath с номером столбца, который я хочу. есть ли лучший способ сделать это? –

+0

Вы можете сделать это в одном выражении XPath, используя селекторные ролики http://stackoverflow.com/questions/3139402/how-to-select-following-sibling-xml-tag-using-xpath –

+0

, что бы вы использовали вместо xpaths, затем ? – KJW

0

Предполагая, что у вас есть атрибут вашего элемента с именем «XPath» вы можете сделать следующее:

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

Хотя звуками него вы пытаетесь достичь чего-то еще здесь вы не поделились с нас еще. Вы хотите, чтобы селен создал xpath для вас? Это невозможно.

6

Вопрос, который вы задали, не имеет для меня никакого смысла. Я предполагаю, что может быть веская причина для вас «хотеть это сделать»!

Ваша строка кода

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

ничего не вернется, потому что нет атрибута «XPath» в HTML элементов. Пожалуйста, ознакомьтесь с основными сведениями о том, что означает xpath.

, если у меня есть HTML элемент, как показано ниже

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

я могу получить значение атрибута с помощью

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

Это даст мне значение «значения» атрибута

или

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

такой же, как указано выше!

0

Вы можете создать XPaths с JavaScript:

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

Он возвращает массив а не String, потому что, если на вашей странице будет меньше или больше элементов с соответствующим тэгом/innerText, вы захотите узнать. Вы можете определить размер массива.

0

Почти такая же ситуация со мной:

У меня есть элемент в таблице, но я не знаю, в какой колонке он находится (как некоторое имя пользователя во всех именах пользователей). Мне нужно найти определенную строку с именем пользователя и нажать кнопку «активировать» только для этого пользователя. (текст имени пользователя находится во втором столбце, который является td [2], и кнопка находится в пятом столбце, который является td [5]). Поэтому мне нужно, чтобы запустить все столбцы один за другим, чтобы найти пользователя, а затем нажмите его кнопку:

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

Перед переборе, использовать этот класс. Затем, когда вы findXPATHIDFromWebElement

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; 
} 
} 

Другой обертка класс для генерации идентификаторов из документов размещен по адресу: http://scottizu.wordpress.com/2014/05/12/generating-unique-ids-for-webelements-via-xpath/

9

Вы также можете использовать это, чтобы ползать и генерировать 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; 
} 
+2

Вау! Вы просто сделали мой день! Благодаря! – ViaSat

+0

Ты потрясающий! Благодаря! –

+0

Это очень хорошее решение. Большое спасибо !! Я так счастлив, что хочу поцеловать тебя в рот! –

0

JavaScript fnction для генерации XPath

XPath/локатор представляет собой способ адресации элемента, перемещаясь по древовидной структуре.

Абсолютный XPath (/):/HTML/тело/DIV [5]/дел [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 [@ ид = 'социально-медиа']/уль/li [3]/а

//Element.TagName[@id="idvalue "и @ class =" classValue "и text() =" innerHTML data "] ИЛИ вы можете использовать. (точка),. является псевдонимом для текста(), если вы знаете, что содержание вы ищете где-то внутри указанного тега, вы можете использовать этот

Пример запуска в консоли [= «innerHTML данные».]:

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"); 
0

Я думаю, что это не какая-либо специальная функция, доступная для получения xpath искомого элемента. Для этого сначала вам нужно найти элемент вручную, а затем получить xpath через функции getXpath.