0

If I have several hyperlinks on the page listed in a grid, and I just want to get focus to the first hyperlink, is there a way to get ref to an a tag's href based on part of the href text?

example, lets say the page has a bunch of hyperlinks with car names:

<a href="/Customers/7">Adam Backwell</a>
<a href="/Customers/12">Eric Mebratu</a>
<a href="/Customers/5">Dave Johnson</a>
<a href="/Customers/54">Tom Rogan</a>

So I want to do something like this for my xPath:

"//table[@id='{0}']/a[href{1}]", usersGridId, "/Customers/");

So get the first hyperlink with /Customers/ in its href. I don't know if you can do just partial string matches..or in other words regex with XPath can you? In this case I don't want to be dependent on the CustomerId because I don't know what that Id will be as the grid is dynamic. All I care about it grabbing reference to the first hyperlink in the grid list, no matter who it is.

UPDATE:

Forgot to add that I'm using XPath with the Selenium Web framework.

UPDATE:

duh, just realized I already have ref to that table (you don't see that code here though..sorry)

So I'm doing like grid.FindElement(By.XPath(xPath)); where grid references already a table element. Within this table is a tbody so I'm tryign to get to the a element like this now:

IElement gridTable = GetCustomerGrid(); // now represents the table element that holds the customer list
xPath = string.Format("/tbody[@id='{0}']/a[1](contains(@href,'{1}')]", usersGridContainerId, "/Customers");
IWebElement hyperlink = gridTable.FindElement(By.XPath(xPath));

no luck on this one either.

also tried the following based on the updated code above:

string.Format("/tbody[@id='{0}']/a(contains(@href,'{1}')]",usersGridContainerId, "/Customers"); // did not find the hyperlink
string.Format("/tbody[@id='{0}']/a[1](starts-with(@href,'{1}')]",usersGridContainerId, "/Customers"); //invalid XPath Syntax error
string.Format("//tbody[@id='{0}']/a(contains(@href,'{1}')]",usersGridContainerId, "/Customers");
string.Format("//tbody[@id='{0}']/a(starts-with(@href,'{1}')]",usersGridContainerId, "/Customers");

Here's the structure of the page where I'm trying to get at the hyperlink

<div class="table">
    <table id="customerList">
        <thead>
            <tr>
                <th class="column1">ID</th>
                <th class="column2">Name</th>
                <th class="column3">Email</th>
            </tr>
        </thead>
        <tbody id="custListContainer">
            <tr>
                <td class="column1">7</td>
                <td class="column2"><a href="/Customers/7">Joe Smith</a></td>
                <td>[email protected]</td>
            </tr>
        .. next user, and so on
        </tbody>
    </table>
</div>

UPDATE:

tried this, no luck:

string xPath = (string.Format("//tbody[@id={0}]/tr/td/a(starts-with(@href, {1})", usersTableId, " /Customers/"));
OurSeleniumDriverInstance.FindElement(By.XPath(xPath ));
1
  • 1
    about to pull my hair out at this point....really frustrating. Commented Mar 7, 2012 at 17:51

3 Answers 3

3

While you can do that with XPath as shown by yajoe, I would also suggest using LINQ to XML if you can:

var query = doc.Descendants("table")
               .Where(table => (string) table.Attribute("id") == usersGridId)
               .Elements("a")
               .Where(a => a.Attribute("href").Value.StartsWith("/Customers/"));

I prefer this as it keeps the "data" parts separate to the "code" parts, much like a parameterized SQL statement.

(Of course, it does rely on you using .NET 3.5 or higher.)

Sign up to request clarification or add additional context in comments.

10 Comments

well that makes sense as you can use LINQ over xml...thanks. More elegant.
@CoffeeAddict: Well it will only work if you've got an XDocument or XElement, not an IWebElement... if you can get it as real XML, it should be easy... but if the preferred way of doing this in Selenium is to use XPath, that makes things harder.
@CoffeeAddict: In XPath, all the "special" parts (operators, slashes etc) are embedded in the string, along with the values. Compare that with the LINQ to XML version, where the values are just expressions, there are separate methods, operators etc. For example, suppose usersGridId could include a single quote - you'd have to escape it in the XPath version, but not in the LINQ to XML version.
@CoffeeAddict: It's more than that - it could all be dynamic, but you'd still have the separation between the values and the code. Likewise I could imagine a version of XPath which allowed you to refer to "variables" which could explicitly have their values set externally. I'd still prefer the LINQ to XML way as it gives more compile-time support (no need to use a separate tool to validate the XPath first) but it's a fundamental difference.
FYI, I updated with a completely different route..I think I had the wrong element to begin with...see the update in the original post.
|
3

Yes, xpath and xquery support matching substrings. The catch is you need to use one of the functions to do it. Your xpath would look like the following (well, your C# to generate xpath...):

"//table[@id='{0}']/a[starts-with(@href,'{1}')]", usersGridId, "/Customers/");

All of the functions are defined here: http://www.w3schools.com/xpath/xpath_functions.asp

Edit: Added the '@' to indicate href is an attribute. Thanks for the catch.

Edit #2: I don't know why my answer was unaccepted -- the xpath is correct and works. Something that sticks out to me is it's unlikely the a tag is a child of the table tag. Are you missing the tr and td tags in between?

1 Comment

it's not working....made sure the element is there on the page and that my syntax matches yours, i.e. string xPath = string.Format("//table[@id='{0}']/a[starts-with(@href,'{1}')]", usersGridId, "/Customers/");
1

You can use the XPath starts-with function:

string.Format("//table[@id='{0}']/a[starts-with(@href,'/Customers/']",
       usersGridId);

NOTE Your XPath was not structured correctly, href is an attribute, so needs to be prefixed with the @ symbol to indicate that it is on the attribute axis.

2 Comments

thanks yea I did actually add the @ after posting...caught it.
yea it's not working....string xPath = string.Format("//table[@id='{0}']/a[starts-with(@href,'{1}')]", usersGridId, "/Customers/");

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.