I've tried using webelement(and IWebElement) and string lists, but i keep getting errors. How I do get a list or strings of all the elements text by XPath? I have all Selenium references. Do i need some java.util dll? Should I implement a foreach loop?
I don't know what exactly you want to do but you can get element text using following code.
public List<String> policy1Details = new List<String>();
public void PolicySummary1(int i)
{
//var driver = new FirefoxDriver();
policy1Details.Clear();
var psummary = driver.FindElements(By.XPath("//text()"));//give your xPath.
//var psummary = driver.FindElement(By.XPath("//div[#id='PolicyDetails_" + i + "']/div/table"));
foreach (IWebElement d in psummary)
{
//resultText.Add(d.Text);
policy1Details.Add(d.Text);
}
}
if any issue the let me know.
Here is the topic with a similar question! - XPath to get all child nodes (elements, comments, and text) without parent
And here is the quote from there!
child::* selects all element children of the context node
So you can do the:
var childs = parent.findElements(By.xpath("./child::*"));
Also here is the documentation of XPath, you can read more here!
Related
I am trying to get all the innertext from a list of "li"-elements. It seems I am hitting something, there are 19 elements in the variable has, but I don't know how to pick out the actual innertext values:
string xpath = "//h1[#title='UL']//li";
IElementHandle[] has = await ((IPage)pageTabel).XPathAsync(xp);
IJSHandle ha = has[0].GetPropertiesAsync("value");
I think e.g.
foreach (var listItem in has)
{
Console.WriteLine((await listItem.GetPropertyAsync("textContent")).RemoteObject.Value.ToString());
}
would work. I don't know whether browser's also implement the (originally IE only) innerText property, if they do then of course above doing GetPropertyAsync("innerText") instead should also work.
If you'd prefer a strongly typed experience then PuppeteerSharp.Dom provides a set of extensions to PuppeteerSharp.
Install PuppeteerSharp.Dom from Nuget.org then you can use the strongly typed extensions.
// Add using PuppeteerSharp.Dom; to access XPathAsync<T>
string xpath = "//h1[#title='UL']//li";
var has = await ((IPage)pageTabel).XPathAsync<HtmlListItemElement>(xpath);
foreach (var listItem in has)
{
var textContent = await listItem.GetTextContentAsync();
}
I have to print all the text of the web elements, so i am storing the web elements in list "test" and then getting text of each web element and keep them adding to other list "Title".
Now when i am trying to print all the elements of list "Title".But only the text of 1st element is printed.
Please help me to find where i am going wrong.
public void PrintText()
{
var Title = new List<string>();
IList <IWebElement> test=Controls.GetWebElementList(X-path);
foreach (var g in test)
{
Title.Add(Controls.GetText(x-path));
}
foreach (var h in Title)
{
Console.WriteLine(h);
}
}
It's not that clear how Controls.GetWebElementList() is defined.
Ideally to extract the texts you have to induce WebDriverWait for VisibilityOfAllElementsLocatedBy() and you can use the following Locator Strategy:
IList <IWebElement> test = new WebDriverWait(driver, TimeSpan.FromSeconds(20)).Until(ExpectedConditions.VisibilityOfAllElementsLocatedBy(By.XPath("X-path")));
Your code looks fine.
Try to verify the first list to print their values.
And then run again, maybe your first line had only one value.
I have multiple input HTML tags on same page having same id and name or class,
Now How should I find 2nd or 3rd.. etc input. I can work with arrays so Do we have some function which will return all the textBox(input tag) from that page.
First you create a list with FindElements, then you can iterate through that list. For example:
var allTextBoxes = driver.FindElements(By.TagName("input"));
foreach(var textBox in allTextBoxes)
{
textBox.DoSomething();
}
You can use a for-loop as well:
for(int i = 0; i < allTextBoxes.Count; i++)
{
allTextBoxes[i].DoSomething();
}
Or if you want a specific Element, in example the 3rd:
allTextBoxes[2].DoSomething();
Expanding on Anaxi's answer,
If you are using the PageObject framework you can do it like this and set the FindsBy attribute on a property:
[FindsBy(How = How.Id, Using = "YourId")]
public IList<IWebElement> ListOfWebElements { get; set; }
i dont know about selenium... but to select element of html page you can use HtmlAgilityPack..
HtmlWeb hw = new HtmlWeb();
HtmlDocument doc = hw.Load(#"http://example.com");
HtmlNode node = doc.DocumentNode.SelectNodes("//div[#class='your_class_name']");
it will return a list of node that contains your_class_name.. then find and use the one you want.
to select all the input tags from that page you can use
foreach (var input in doc.DocumentNode.SelectNodes("//input"))
{
//your logic here
}
hope it helps..
In C# I use FindElements then ElementAt():
var foo= Driver.FindElements(By.XPath("//div[#class='your_class_name']"));
var foo2= foo.ElementAt(1);
If it's 10 elements with the same ID (which is HORRIBLE) and I'd like to grab the 8th element, I just use ElementAt(8); (or index 7 or however you're set up).
It's a tough call. I'd much rather have them fix the code but in some cases that's just not going to happen... at least not in the near future.
Hope this helps.
Working code 1:
Driver.Instance.FindElement( By.XPath("//a[contains(#href,'" + PartialLinkHref + "')]" ));
Working code 2:
ReadOnlyCollection<IWebElement> linkList = Driver.Instance.FindElements(By.TagName("a"));
for (int i = 0; i < linkList.Count ; i++)
{
if (linkList[1].GetAttribute("href").Contains(PartialLinkHref))
{
element.SetElement(linkList[i]);
return element;
break;
}
}
The problem with your initial selector is that you're missing the // in front of the selector. the // tells XPath to search the whole html tree.
This should do the trick:
Driver.Instance.FindElement(By.XPath("//a[contains(#href, 'long')]"))
If you want to find children of an element, use .// instead, e.g.
var element = Driver.Instance.FindElement("..some selector..")
var link = element.FindElement(".//a[contains(#href, 'long')]"))
If you want to find a link that contains text and not by the href attribute, you can use
Driver.Instance.FindElement(By.XPath("//a[contains(text(), 'long')]"))
I don't think the problem is your selector, I think it's the object you're trying to return the results of FindElements to.
In c#, FindElements returns a ReadOnlyCollection<IWebElement> object, not a List object. If you change your linkList definition, it should work:
ReadOnlyCollection<IWebElement> linkList = Driver.Instance.FindElements(By.TagName("a"));
You may also need to add this using:
using System.Collections.ObjectModel;
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!
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.
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
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"));
}
you can do a FindElement(By.tag("body")) to return a list of WebElements and then parse the results as you suggest.
You can try this:
Actions newTab = new Actions(web driver);
newTab.ContextClick(element).SendKeys(Keys.ArrowDown).SendKeys(Keys.ArrowDown).SendKeys(Keys.Return).Build().Perform();
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;
}