PositiveGuy
PositiveGuy

Reputation: 47733

XPath - way to select an element based on partial string

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 ));

Upvotes: 0

Views: 7531

Answers (3)

user1251108
user1251108

Reputation:

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?

Upvotes: 3

Jon Skeet
Jon Skeet

Reputation: 1499730

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.)

Upvotes: 3

ColinE
ColinE

Reputation: 70122

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.

Upvotes: 1

Related Questions