I'm looking to get the class attribute of every WebElement
on the page quickly with selenium. Currently, I'm doing the following:
allElements = new ArrayList<WebElement>(m_webDriver.findElements(By.cssSelector("*")));
for (WebElement element : allElements) {
String className = element.getAttribute("class");
}
This process is incredibly slow, taking upwards of thirty seconds on a page with 500 elements. I've tried parallelizing the getAttribute
call, which is the slowest part of the method, but there was no speed increase. This leads me to believe that every call to getAttribute
is fetching information instead of storing it locally.
Is there a faster or parallelizable way to do this?
The getAttribute() method fetches the text contained by an attribute in an HTML document. It returns the value of the HTML element's attribute as a string. If a value is not set for an attribute, it will return a NULL value. For attributes with Boolean values, getAttribute() will return either "True" or NULL.
We can find an element using the attribute class name with Selenium webdriver using the locators - class name, css, or xpath. To identify the element with css, the expression should be tagname[class='value'] and the method to be used is By. cssSelector.
We can get the css class name of an element with Selenium webdriver. To obtain the class name attribute of an element in the html document, we have to use the getAttribute() method. Then the class value is passed as a parameter to the method.
Type “css=input[type='submit']” (locator value) in Selenium IDE. Click on the Find Button. The “Sign in” button will be highlighted, verifying the locator value. Attribute: Used to create the CSS Selector.
The problem is, you cannot make selenium send batch getAttribute()
calls for multiple elements. Here is a similar problem I've looked into - it is about making isDisplayed()
work for multiple elements without making JSON Wire protocol requests for every element in a list:
But, as opposed to this isDisplayed()
problem, here we can execute javascript and reliably get the class attribute values for every element on a page, something like this to get you started:
JavascriptExecutor js = (JavascriptExecutor) driver;
js.executeScript("var result = []; " +
"var all = document.getElementsByTagName('*'); " +
"for (var i=0, max=all.length; i < max; i++) { " +
" result.push({'tag': all[i].tagName, 'class': all[i].getAttribute('class')}); " +
"} " +
" return result; ");
I would keep it simple and use an XPath instead of a complex snip of Javascript:
// get all elements where class attribute is not null
List<WebElement> allElements = m_webDriver.findElements(
By.xpath(".//*[@class and not(ancestor::div[contains(@style,'display:none')])]")
);
for (WebElement element : allElements) {
String className = element.getAttribute("class");
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With