How Can i get this Xpath - c#

I got the id for capturing.
//button[contains(text(),'Delete')][1]
//button[#id='deletebtn']
but its have 10 duplicate values.can't identify unique thing for capture the element.Please Help me to resolve

As you haven't shared full HTML I am assuming you want use the first locator of 10 matches.
You can use
//(button[contains(text(),'Delete')])[1]
instead of
//button[contains(text(),'Delete')][1]
In case, suppose you want to use an another element then change the match number. Like below,
//(button[contains(text(),'Delete')])[3]
or
//(button[contains(text(),'Delete')])[4]
Note: Selenium by default picks the first element if there are more than one match.
Always check your xPath in chrome console to make sure it is unique.
Press F12 in Chrome.
Go to elements section
Search ( CTRL + F)
Place the xpath and see, if your desired element is getting highlighted with 1/1 matching node. This means, your xPath is unique.

You are using the wrong syntax to write the index based xpath.
Correct syntax for index based XPath-
(//button[contains(text(),'Delete')])[10]
PS: You can verify in SelectorsHub if your xpath is correct or not.

Related

Can't find CssSelector with Selenium

I am trying to do some automated tests with Selenium, but I have a problem. I want to be able to press a special button, but this button does not have an ID or Class, which is the first thing I try to look for.
I Think that I need to use the CssSelector, but how exactly should I write to find the correct button in my test?
driver.FindElement(By.CssSelector(??))
You can use the sibling <table> id as starting point
driver.FindElement(By.CssSelector("#tbl_bestallningslita ~ button"));
Or use the onclick attribute (partial)
driver.FindElement(By.CssSelector("[onclick*='btn_taBort']"));
Any of the below CSSLocators should help:
button[accessKey="T"]
OR
button[onclick="folkbokforing_form.btn_taBort.click()"]
You can use xpath too, xpath gives you more flexibility over cssselector although its quite slower than cssselector.
driver.findElement(By.XPath("*//button[#onclick='folkbokforging_form.btn.taBort.click()']"));
or use combined two attributed xpath,
driver.findElement(By.XPath("*//button[#accesskey='T' and contains(#onlcinck,'btn_taBort.click()')]");

Find elements on webpage with Selenium

I have XPath
/html/body/div[#id='page']/div[#id='page-inner']/div[#id='main-box']/div[#class='in1']/div[#id='content-and-context']/div[#id='content']/div[#class='under-bar']/table[#class='flights']/tbody/tr[#id='flight-932539']/td[2]:
But flight-number are changes. Can I find Elements with part XPath ?
I use foreach() and write data for every flight.
this is html code:
First thing first: don't use absolute path. Even the smallest change in the html invalidate the path, especially in dynamic applications. Your xpath could easily be //tr[#id='flight-932539']/td[2]
As for your question, you can use contains() for partial id
//tr[contains(#id, 'flight-')]/td[2]
As Guy mentioned xpath above, for same you can easily use findElements to find all the flight details and then according perform you actions using for loop.
List<WebElement> WebElements = driver.findElements(By.xpath("//tr[contains(#id, 'flight-')]/td[2]");
for(WebElement element : WebElements){
//perform any operation like for click you can use
element.getText();
}
Above example is in JAVA you can do same in C# as well.

Passing a value into an Xpath expression

I am currently writing a test against an e-commerce website. When a user runs a search for a particular product a list of items are being returned. What I am hoping to do is pass a particular value (e.g. the number 2) into my test scenario, at which point can be passed into my XPath expression (nth-child), enabling the item to be selected.
The XPath is incorrect and not sure how to fix it. Would appreciate if someone could help.
[Then(#"I select item '(.*)' from the search results")]
public static void WaitAndSelectAnItem(int item)
{
{
Driver.Instance.FindElements(By.CssSelector("#productGrid"));
var itemToSelect = Driver.Instance.FindElement(By.XPath(string.Format("//#class='itemContainer:nth-child({0})'", item)));
itemToSelect.Click();
}
}
Result Message: The given selector //#class='itemContainer:nth-child(3)' is either invalid or does not result in a WebElement. The following error occurred:
InvalidSelectorError: Unable to locate an element with the xpath expression //#class='itemContainer:nth-child(3)' because of the following error:
TypeError: The expression cannot be converted to return the specified type.
nth-child is not part of the XPath language and is actually a CSS selector pseudo-class.
Instead, you've probably meant:
(//*[#class='itemContainer'])[{0}]
Note that indexing in XPath starts with 1 - make sure you are actually getting the correct item.
Alternatively, you can use findElements() to find all "itemContainers" and then get the desired one by index. Note that it is 0-indexed here:
Driver.Instance.FindElements(By.XPath("//*[#class='itemContainer']"))[item]
Assuming that the "item container" is a DIV tag, if not div replace div by the right tag, * will work as well but there may be chances that you get more elements which you don't want.
Try this:
(//div[#class='itemContainer'])[1]
Replace 1 by your item indices.

Check if element in XML exists that ends with matching string

I can see a way of searching for an element within XML by just going:
if(doc.SelectSingleNode("//mynode")==null)
But what I'm more interested in, is finding an element that matches the part of the name. Something like:
doc.SelectSingleNode ...that contains "table" in it.
So if I had a node called "AlinasTable", I want it to find that. Why it matters is because my node can inconsistently contain anything that comes before "table", like "JohnsTable" - in which case I'd want that to be returned. So something more generic.
Cheers.
You can use the contains function, as in the following XPath expression:
doc.SelectSingleNode("//*[contains(name(), 'Table')]")

Why is this seemingly simple Xpath navigation not working?

I'm having what seems like a really simple problem. I'm trying to navigate to an element in HTML by Xpath, and can't seem to get it to function properly.
I want to grab a span from the html contents of a page. The page is fairly complex, so I've been using Firebug's "get element by xpath" and pasting the result into my code. I've noticed it's slightly different than the xpath you get from doing the same thing in Chrome, but they both seem to direct to the same place.
The html I'm trying to navigate is found here. The field I'm trying to access via xpath is the first "Results 1 - 10 of n".
Based on FireBug's 'inspect element' the xpath should be: /html/body/div/center/table/tbody/tr[6]/td/table/tbody/tr/td[2]/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td/table/tbody/tr/td/span
However when I try to use this xpath to identify the element in a C# codebehind, it gives me a number of errors that that path cannot be found.
Am I doing something wrong here? I've tried a number of permutations of the xpath and I don't understand why this wouldn't be cooperating within code.
Edit: I'm having this problem both in HTMLAgilityPack (but managed to hack out a bad solution using regexes instead) and a SELECT statement modeled after the answer found here
Edit 2: I'm trying to figure out this issue using Yahoo's free proxy as shown in the example here:
var query = 'SELECT * FROM html WHERE url="http://mattgemmell.com/2008/12/08/what-have-you-tried/" and xpath="//h1" and class="entry-title"';
var url = "http://query.yahooapis.com/v1/public/yql?q=" + query + "&format=json&callback=??";
$.getJSON(url,function(data){
alert(data.query.results.h1.content);
})
I'm having the same problems with HTML agility pack but I'm more interested in getting this part to work. It works for the provided URL that the answerer gave me (seen above). However when I try to use even simple xpath expressions on the http://nl.newsbank.com url, I get errors that no object has been retrieved every time, no matter how basic the xpath.
Edit 3: I thought I'd elaborate a little more on the big picture of the larger problem I'm trying to solve of which this problem is a critical component in the hopes that maybe it provides a little more insight.
To learn basic ASP.NET development skills from scratch, I decided to make a simple web application, based around the news archive search at http://nl.newsbank.com/. In its current iteration, it sends a POST request (although I've now learned you can use a GET request and just dump the body at the end of the URL) to send search criteria, as if the user entered criteria in the search bar. It then searches the response (using RegExes, not Xpath because I couldnt get that working) for the "Results 1-n of n" span, extracts n, and dumps it in a table. It's a cool little tool for looking up news occurrence rates over time.
I wanted to add functionality such that you could enter a date range (say May 2002 - June 2010) and run a frequency search for every month / week in that range. This is very easy to implement conceptually. HOWEVER the problem is, right now all this happens server side, and since there's no API, the HTTP response contains the entire page, and is therefore very bandwidth intensive. Sending dozens of queries at once would swallow absolutely unspeakable amounts of bandwidth and wouldn't be even a little scalable.
As a result I tried rewriting the application to work client-side. However because of the same-origin policy I'm not able to send a request to an external host from the client-side. HOWEVER there is a loophole that I can use a free Yahoo proxy that makes the request and converts it to JSON, and then I can use the JSON exception of the Same-Origin Policy to retrieve that data from the proxy.
Here's where I'm running into these xpath problems specific to http://nl.newsbank.com. I'm not able to retrieve html with any xpath, and I'm not sure why or how I can fix it. When debugging in VS2010, I'll receive the error Microsoft JScript runtime error: Unable to get value of the property 'content': object is null or undefined
As paul t. already mentioned in a comment, the TBODY elements are generated by the webkit engine. The next problem is that the DIV between the BODY and CENTER does not exist on the page by default. It is added by an JS statement on line 119.
After stripping out the DIV and TBODY elements like
/html/body/center/table/tr[6]/td/table/tr/td[2]/table/tr/td/table/tr/td/table/tr/td/table/tr/td/span
i can successfull select a node with the HthmlAgilityPack.
Edit: don't use tools like Firebug for getting an XPath value on a website. Don't even use it if you just want wo look at the source of the page. The problem with Firebug is, that it will show you the current DOM document tree which probably on almost every is already (heavily) modified by JS.
Your sample HTML page's elements haven't got many classes to select on, but if you're interested in the first <span> element that contains "Results: 1 - 10 of n", you can use an XPath expression that explicitly targets this textual content.
For example:
//table//span[starts-with(., "Results:")]
will select all <span> elements, contained in a <table>, and that contain text beginning with "Results:" (the //table is not strictly necessary in your case I think, but might as well restrict a little)
You want the first one of these <span>, so you can use this expression:
(//table//span[starts-with(., "Results:")])[1]
Note the brackets around the whole previous expression and then [1] to select the first of all the <span> matching the text
It may sound kind of simplistic, but the element you are looking for is the only doc element that is using the css class "basic-text-white". I would think this would be a lot easier to find and extract than a long xpath. Web-scraping is never a stable thing, but I would think this is probably as stable as the xpath. Trying to debug the xpath just about makes my eyes bleed.

Categories

Resources