Selenium get dynamic id from xpath - selenium

Is there a way in Selenium RC to get the id from the xpath?
If I have the xpath
/html/body/div/div//input
I want to get the id of all the nodes associated to the xpath

You can use getAttribute in combination with getXpathCount.
A Selenium 1 example in Java would be:
int inputs = selenium.getXpathCount("/html/body/div/div/descendant::input").intValue();
for (int i=1; i<=inputs; i++) {
System.out.println(selenium.getAttribute("/html/body/div/div/descendant::input[" + i + "]#id"));
}
A Selenium 2 example in Java would be:
List<WebElement> inputs = driver.findElements(By.xpath("/html/body/div/div/descendant::input"));
for (WebElement input : inputs) {
System.out.println(input.getAttribute("id"));
}

You can get that by running a javascript, using this.browserbot.findElement('/html/body/div/div//input'):
Of course, this depends on the source language, but it would be something like this (in perl, untested):
#first count the number of inputs with ids
my $count = $selObj->get_xpath_count('/html/body/div/div//input[#id]');
#build a javascript that iterates through the inputs and saves their IDs
my $javascript;
$javascript .= 'var elements = [];';
$javascript .= "for (i=1;i<=$count;i++)";
$javascript .= " elements.push(this.browserbot.findElement('/html/body/div/div/input['+i+']').id);";
#the last thing it should do is output a string, which Selenium will return to you
$javascript .= "elements.join(',');";
my $idString = $selObj->get_eval($javascript);
I always thought there should be a more direct way to do this, but I haven't found it yet!
EDITED based on the comments, the for loop count should start from 1 and include $count, also the findElement line only needs one forward-slash before input.
EDIT2 Adding a completely different idea based on further comments:
Selenium's javascripts that get attached to every page include a function called eval_xpath that returns an array of DOM elements for a given query. Sounds like what you want?
Here's what I think the javascript would look like (again, untested):
var elements = eval_xpath('/html/body/div/div//input',this.browserbot.getCurrentWindow().document);
var results = [];
for (i=0;i<elements.length;i++){
results.push(elements[i].id);
}
results.join(',');

Related

Get error [object Text]. It should be an element

Trying to get the text from the div with xPath. Finds information in the browser good, but when i try to run with an idea than i get error:"is: [object Text]. It should be an element."
List<WebElement> priceGameWebElement = webDriver.findElements(By.xpath("//div[contains(#class,'search_price')]" +
"/text()[normalize-space()][1]"));
What do I need to do to make everything work?
You can "interrupt" your query before the /text()... part like this:
List<WebElement> priceGameWebElement = webDriver.findElements(By.xpath("//div[contains(#class,'search_price')]"));
Then you should get a List<WebElement> which contains the elements with the text() nodes for further distinction. They could probably be queried with the .getText() function.
If for some reason you cannot exclude text() from XPath and you need just extract the text of the element, then there is a workaround: use method document.evaluate() from JavaScript.
Code example:
String textObjectXpath = "\"//*[local-name() = 'text'][#x='8']/text()\"";
String script = "var element = document.evaluate("
+ textObjectXpath
+ ", document, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;"
+ "if (element) {return element.nodeValue;}";
String extractedText = (String) ((JavascriptExecutor)driver).executeScript(script);
The if statement "if (element) {return element.nodeValue;}" could be omitted if you don't care about the scenario when the element will be without text. In a such case, you may want to replace the line with "return element.nodeValue;"

I need to go few websites and grab specific data set

Looking for a way to go to a few websites (10 sites) and grab a set of data, need a proper way to do since I am new to coding.
code:
WebUI.openBrowser('');
WebUI.navigateToUrl("www.site1.com");
WebUI.maximizeWindow();
String text1 = WebUI.getText(findTestObject("xpath"));
Do I need to do this for all the 10 websites?
Let's say you have the 10 URLs in an array. Create another empty array that will hold the text values:
WebUI.openBrowser('');
def mySites = ["www.site1.com", "www.site2.com", "www.site3.com", "www.site4.com", "www.site5.com", "www.site6.com", "www.site7.com", "www.site8.com", "www.site9.com", "www.site10.com"];
def myTexts = [];
Then loop your above code in a for loop, and add the text values to the array (note: xpath element name is the same for all the sites in this example, you should edit that according to your needs):
for(i=0; i<mySites.size; i++){
WebUI.navigateToUrl("www.site1.com");
WebUI.maximizeWindow();
myTexts << WebUI.getText(findTestObject("xpath"));
}

Xpath con-cat is possible with reference to List<WebElement> object in selenium?

Scenario with Example:
10 Different Row in Table (e.g. //a[#class='*******'] ).
Need to Retrieve different Value from each Row
Retrieving it using List
In given example, Temp1 getting executed and iterate as required, As information need to retrieve from the same and got it through getAttribute(" ").
Need to retrieve Temp2 value which is dependent on object findList. findSubInfo is having Following Siblings from mainList. Its only addition on following siblings in to List exa.(findList).
Issue is :
If I execute 1st provision, as independent node, It always retrieve first row's value. (Which is Obvious)
If I execute 2nd provision, with xpath + List object using con-cat it throws xpath Syntax issue.
Question :
How can retrieve all information from object's siblings, where object List<WebElement> findList is pointing ?
Trial :
By mainList = By.xpath("//a[#class='*******']");
By findSubInfo = By.xpath("//a[#class='*****']//following::div[#class='****']");
List<WebElement> findList = driver.findElements(mainList);
for (WebElement webElement : findList ) {
if (webElement.isDisplayed()) {
String temp1= "Info1:" + webElement.getAttribute("ng-href");
String temp2= "Info2: " + driver.findElement(findSubInfo).getText();
}
}
OR
String mainList "//a[#class='*******']";
String findSubInfo = "//following::div[#class='****']";
List<WebElement> findList = driver.findElements(By.xpath(mainList));
for (WebElement webElement : findList ) {
if (webElement.isDisplayed()) {
String temp1= "Info1:" + webElement.getAttribute("ng-href");
String temp2= "Info2: " + driver.findElement(By.xpath(webElement + findSubInfo )).getText();
}
}
Exception Details:
SyntaxError: Failed to execute 'evaluate' on 'Document': The string
'[[ChromeDriver: chrome on XP (3208ef0a2ffd32812c33e159291eebe4)] ->
xpath: //a[#class='noDecoration
addPointer']]//following::div[#class='assignedAccountMasterAddress']'
is not a valid XPath expression.
If you want to search for element with related XPath starting from current element (webelement), try
# Note that it should start with the dot
String findSubInfo = "./following::div[#class='****']";
# use webElement.findElement instead of driver.findElement. No XPath concatenations needed
String temp2= "Info2: " + webElement.findElement(By.xpath(findSubInfo)).getText();

Incrementing value with Selenium IDE

How do I increment value of img path when said path looks like this?
//ab[x]/img
X value increasing by 1 and has a limit of 50.
Trying to write a test case on how to click on several images on website.
Edit: Just wanted to add that I'm just starting with Selenium IDE and using standart commands.
Solution 1: Format your xpath path selector
for(int i=1; i<=numberOfImages; i++) {
String path = String.format("//ab[%d]/img", i);
WebElement image = driver.findElement(By.xpath(path));
if(image != null) {
image.click();
}
}
Solution 2: Select all elements that "//ab/img" returns and iterate over them.
String path = "//ab/img";
List<WebElement> imgElements = driver.findElements(By.xpath(path)); //notice the plural
for(WebElement image : imgElements) {
image.click();
}

Getting text from a node

I have a piece of HTML like this:
<a href="/something">
Title
<span>Author</span>
</a>
I got a WebElement that matches this HTML. How can I extract only "Title" from it? Method .getText() returns "Title\nAuthor"...
You can't do this in the WebDriver API, you have to do it in your code. For example:
var textOfA = theAElement.getText();
var textOfSpan = theSpanElement.getText();
var text = textOfA.substr(0, textOfA.length - textOfSpan.length).trim('\n');
Note that the trailing newline is actually part of the text of the <a> element, so if you don't want it, you need to strip it.
Here is the method developed in python.
def get_text_exclude_children(element):
return driver.execute_script(
"""
var parent = arguments[0];
var child = parent.firstChild;
var textValue = "";
while(child) {
if (child.nodeType === Node.TEXT_NODE)
textValue += child.textContent;
child = child.nextSibling;
}
return textValue;""",
element).strip()
How to use in this:
liElement = driver.find_element_by_xpath("//a[#href='your_href_goes_here']")
liOnlyText = get_text_exclude_children(liElement)
print(liOnlyText)
Please use your possible strategy to get the element, this method need an element from which you need the text (without children text).
If using Python:
[x['textContent'].strip() for x in element.get_property('childNodes') if isinstance(x, dict)]
Where element is your element.
This will return ['Title', ''] (because there are spaces after span).
you can use jsexecutor to iterate the child nodes, trap the textNode 'Title' and then return its content like below
WebElement link = driver.findElement(By.xpath("//a[#href='something']"));
JavascriptExecutor js = ((JavascriptExecutor)driver);
String authorText = (String) js.executeScript("for(var i = 0; i < arguments[0].childNodes.length; i++) {
if(arguments[0].childNodes[i].nodeName == \"#text\") { return arguments[0].childNodes[i].textContent; } }", link);
The javascript code block above iterates both textNode ('Title') and SPAN ('Author') but returns only the text content of textNode.
Note: Previous to this, I have tried including text node in xpath like below, but webdriver throws invalidselector exception as it requires element not textnode
WebElement link = driver.findElement(By.xpath("//a[#href='something']/text()"));
Verify the element present for "//a[normalize-space(text())=Title]". It will return true if the text present inside 'a' tag is 'Title'.