views:

606

answers:

2

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

A: 

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(',');
Ryley
Would you happen to have code to do this in java?
Reflux
I'm sorry, I don't... the only real difference is the selenium functions called, looking at the Java docs, you need `getXpathCount` and `getEval`, both in the `DefaultSelenium` object
Ryley
Ok i figured out how to implement this in java but I have an issue because my nodes are not input[1] to input[i]. My xpath is not an absolute xpath, basically I want all the inputs for the xpath that starts with /html/body/div/div
Reflux
I think you miss understood my last comment. the path is /html/body/div/div//input but I am missing elements between the // because I don't care what is between the //. I don't have an input[1] - input[i] but I do have /html/body/div[1]/div/input[1] and /html/body/div[2]/form/div/input[1]. My xpath syntax should be correct because getxpathcount() gives me the correct number also it evaluates in Xpather.
Reflux
Ahh, that's a bit more tricky.... and now that I've dug around in selenium-core, I have various untested bits for you to try :)
Ryley
The second javascript works. Thanks so much.
Reflux
+2  A: 

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"));
}
Dave Hunt
Your code works too but you spelled descendant wrong, so at first I was getting invalid xpath :P.
Reflux
I've corrected the typo (sorry about that). I would warn however that `//` is not the same as `/descendant::` and you may get some unexpected behaviour. Also, why use all that JavaScript when there's a Selenium command for getting an attribute?
Dave Hunt
My only argument for my code (Selenium 1) is that if you have a ton of elements, my code will only make one trip to the browser instead of one per element. In my experience, that can take a long, long time. In Selenium 2, your code seems way better, definitely.
Ryley