8

I want to extract some information from the DOM with Selenium. I'm using the C# WebDriver.

Looking at the IWebElement interface you can easily extract a given attribute. However, I would like to extract all the attributes of an element without knowing their names in before hand.

There must be some simple way of doing this since there is a method for getting an attribute value if you know its name.

An example:

<button id="myButton" ng-click="blabla()" ng-show="showMyButton" 
     some-other-attribute="foo.bar" />



IWebElement element = driver.FindElement(By.Id("myButton"));
Dictionary<string, string> attributes = new Dictionary<string, string>();
// ???????
// Profit.

Hopefully I'm missing something obvious.

Thanks in advance!

Mark Cidade
  • 98,437
  • 31
  • 224
  • 236
pansarshrek
  • 125
  • 1
  • 1
  • 7
  • Just a few questions...1) Why is it needed? 2) So in your example `button`, what **exactly** would you expect it to return and 3) At a first glance, I suspect this is probably only possible by executing something in JavaScript and parsing the results - this will introduce a dependency and a possible performance issue in your tests - is this acceptable? – Arran Feb 10 '14 at 16:16
  • @Arran : Thanks for responding. 1) It is needed to collect information about where a test failed which we intend to perform some further analysis on further down the road. 2) I would like it to return a collection of all the attributes {id: 'myButton', ng-click: 'blabla()', ng-show: 'showMyButton', some-other-attribute: 'foo.bar' }. 3) Performance is secondary. – pansarshrek Feb 10 '14 at 16:36

6 Answers6

15

The .attributes property in JavaScript will return an array of all the attributes a given element has and it's value.

So what you'll need to do is first get a driver that has the capability to run JavaScript:

IJavascriptExecutor javascriptDriver = (IJavaScriptExecutor)driver;

Now, execute it by:

Dictionary<string, object> attributes = javascriptDriver.ExecuteScript("var items = {}; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;", element) as Dictionary<string, object>;

The idea behind the JavaScript is to use the JavaScript attributes property within the element itself and then pull out the information we need - the name and value of the attribute. The attributes property, in reality, pulls a lot of information about each individual property but we want only two fields. So we get those two fields, put them into a dictionary and WebDriver will then parse it back to us. (It could probably be cleaned up a bit)

It's now a Dictionary and thus you can loop through however you like. The key of each pair will be the name of the attribute, and the value of each pair will be the value of the attribute.

Only tested this with a few elements dotted around the web (here, Google, and a few small web pages) and it seems to work well.

Arran
  • 24,648
  • 6
  • 68
  • 78
8

You can try this:

IWebElement element = driver.FindElement(By.Id("myButton"));

string elementHtml = element.GetAttribute("outerHTML");

This will give you the html of the element. From here, you can parse it, as Arran suggested

Kevin Brechbühl
  • 4,717
  • 3
  • 24
  • 47
rotem
  • 83
  • 2
1
List<IWebElement> el = new List<IWebElement>(); el.AddRange(driver.FindElements(By.CssSelector("*")));

List<string> ag= new List<string>();
for (int b = 0; b < el.Count; b++)
{                    
    ag.Add(el[b].GetAttribute("outerHTML"));
}
Neuron
  • 5,141
  • 5
  • 38
  • 59
BREI
  • 101
  • 2
  • 4
  • Thanks for providing code which might help solve the problem, but generally, answers are much more helpful if they include an explanation of what the code is intended to do, and why that solves the problem. – Neuron May 27 '18 at 20:58
0

you can do a FindElement(By.tag("body")) to return a list of WebElements and then parse the results as you suggest.

madz
  • 456
  • 4
  • 13
0

You can try this:

Actions newTab = new Actions(web driver);
newTab.ContextClick(element).SendKeys(Keys.ArrowDown).SendKeys(Keys.ArrowDown).SendKeys(Keys.Return).Build().Perform();
FiReTiTi
  • 5,597
  • 12
  • 30
  • 58
0

I have created WebDriver Extension based on the first answer

public static List<string> GetElementAttributes(this RemoteWebDriver driver, IWebElement element)
{
    IJavaScriptExecutor ex = driver;
    var attributesAndValues = (Dictionary<string, object>)ex.ExecuteScript("var items = { }; for (index = 0; index < arguments[0].attributes.length; ++index) { items[arguments[0].attributes[index].name] = arguments[0].attributes[index].value }; return items;", element);
    var attributes = attributesAndValues.Keys.ToList();
    return attributes;
}