get element by XPath or CSS via javascript/DOM?

27,439 views
Skip to first unread message

David

unread,
Feb 22, 2012, 7:31:28 PM2/22/12
to Selenium Users
It's nice to see & use Selenium methods to work with object via XPath
and CSS. The basic DOM model offers the common/standard:

document.getElementById

along with

some ways to getElementByClassName, etc.

I was wondering if there exists some javascript code to encapsulate
functionality such as:

document.getElementByXPath (and/or its plural equivalent for multiple
elements)

and/or document.getElementByCss

Could be useful for web development as well as alternative way to work
with elements via the DOM via Javascript if having trouble within
Selenium.

Doing a search, closest I came across are the following, which aren't
explained very well.

http://userscripts.org/scripts/review/23928

http://userscripts.org/scripts/review/24554

Jason

unread,
Mar 2, 2012, 12:05:11 AM3/2/12
to Selenium Users
Hi,

Thanks for posting the question, as well as providing two related
link.

Actually, one of the link contains the answers:
http://userscripts.org/scripts/review/24554

the document.getElementByXPath does exactly what you need (not
extensively tested, but works to me for a few xpath cases)

Just used this function before your other js call, and it works great.

Copied the functions over in case the link goes invalid:

document.createStyleSheet = function(sValue) { var o =
this.createElement("style"); o.type = "text/css"; o.innerHTML =
sValue; this.getElementsByTagName("head")[0].appendChild(o); };

document.getElementByXPath = function(sValue) { var a =
this.evaluate(sValue, this, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (a.snapshotLength >
0) { return a.snapshotItem(0); } };

document.getElementsByXPath = function(sValue){ var aResult = new
Array();var a = this.evaluate(sValue, this, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);for ( var i = 0 ; i <
a.snapshotLength ; i++ ){aResult.push(a.snapshotItem(i));}return
aResult;};

document.removeElementsByXPath = function(sValue) { var a =
this.evaluate(sValue, this, null,
XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE, null); for ( var i = 0 ; i <
a.snapshotLength ; i++ )
{ a.snapshotItem(i).parentNode.removeChild(a.snapshotItem(i)); } };

David

unread,
Dec 8, 2012, 5:11:54 PM12/8/12
to seleniu...@googlegroups.com
Most likely a quote problem because you're executing a javascript string of code with WebDriver but that javascript itself requires an XPath string, where the XPath also happens to require a quoted value. So you may need to escape quotes. The proper fix would be to change one of the quote pairs in the javascript XPath argument like this:

 this.evaluate(\"//div[@guidedhelpid='sharebutton']\",

where we escape out the double quotes because the javascript itself is a string value.

On Thursday, December 6, 2012 1:22:41 PM UTC-8, Malhar wrote:
I'm trying to run webdriver code from java. I copied document.getElementByXpath() in a string(I have static xpath so I can live without xpath variable)

String Script = "var a = this.evaluate('//div[@guidedhelpid='sharebutton']', this, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (a.snapshotLength > 0) { return a.snapshotItem(0); };";
JavascriptExecutor jse = (JavascriptExecutor)driver;
jse.executeScript(Script);


but it gives me syntax error.

SyntaxError: missing ) after argument list


--Mal

Matt

unread,
Mar 13, 2013, 9:01:46 AM3/13/13
to seleniu...@googlegroups.com
Even just executing a simple version such as this is returning the same error:

js.executeScript("document.getElementByXpath('//a[@id='create-channel-button']).click();" );

On Tuesday, March 12, 2013 5:05:06 PM UTC-4, Matt wrote:
I'm trying to do something similar but I'm getting a syntax error.  Any ideas?  If I run the xPath query directly in the browser console it finds what I would expect.. just having trouble running it through Javascript.
Uncaught SyntaxError: Unexpected identifier

Here is the code I'm using -- postNum being an integer variable:

JavascriptExecutor js = (JavascriptExecutor) driver; js.executeScript("var postElement document.evaluate('(//div[@class='vcell link post_bar'])["+postNum+"]//a[@class='vcell link edit']', document, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null); if (a.snapshotLength > 0) { return a.snapshotItem(0); };" );

David

unread,
Mar 13, 2013, 2:26:57 PM3/13/13
to seleniu...@googlegroups.com
Matt, in both your posts, you have syntax errors. Perhaps you didn't get them in browser console because you didn't have to invoke the XPath query within a method call itself (as quoted string).

Your problem is non matching quotes & escaping quotes. Make sure every starting quote has a matching end quote, whether it be single or double quote character. And you can't reuse same quote type so

document.getElementByXpath('//a[@id='value']') does not work when using same quote to quote the string value plus the ID attribute value.

so sometihng like this will be better

 document.getElementByXpath("//a[@id='value']") 

and if you have too much to quoting to work with and need to use both quote types you might also have to resort to escaping quotes sometimes like this

 document.getElementByXpath("//a[@id=\"value\"]")

fix your quoting syntax errors and try again to see if they work. 

David

unread,
Mar 13, 2013, 2:29:46 PM3/13/13
to seleniu...@googlegroups.com
By the way, did you run XPath query in console via XPath finder addon tools like FirePather, XPather, etc. or native javascript?

Did you know that you can execute document.getElementById('value') and other type methods in browser's javascript console? Executing such will return a result and if you have syntax errors already there, you'd see an error or bad result in console. You don't have to test out the code purely in javascriptExecutor.

David

unread,
Apr 30, 2013, 6:16:19 PM4/30/13
to seleniu...@googlegroups.com
Just came across this for getElementByCSS:


not sure how it could be adapted to be callable as

document.getElementByCSS()

would be nice to have...

Jim Evans

unread,
May 1, 2013, 6:11:41 AM5/1/13
to seleniu...@googlegroups.com
XPath over HTML isn't a standard feature for all browsers; there's no World Wide Web Consortium (W3C) standard that applies. This means that any "document.getElementByXPath" JavaScript function is likely to fail in some browsers, most notably IE.

Finding elements by CSS selectors in JavaScript, on the other hand, is easily supported by all modern browsers. The function you're looking for is "document.querySelector()" for single elements and "document.querySelectorsAll()" for multiple elements. In point of fact, when people tell me they're having trouble using findElement(By.cssSelector()) in WebDriver, the first thing I recommend is trying their selector in the JavaScript console using document.querySelector().

David

unread,
May 1, 2013, 1:39:19 PM5/1/13
to seleniu...@googlegroups.com
Thanks for the info Jim. And it looks like I can define an alias to it if I wanted like

document.getElementByCssSelector = document.querySelector;
Reply all
Reply to author
Forward
0 new messages