XPath - 基于部分字符串选择元素的方法

时间:2012-03-07 06:18:05

标签: c# xpath selenium

如果我在网格中列出的页面上有几个超链接,并且我只想将焦点放在第一个超链接上,是否有办法根据部分href文本获取引用标记的href?

示例,假设该页面包含一系列带有汽车名称的超链接:

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

所以我想为我的xPath做这样的事情:

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

所以在其href中获取带有/ Customers /的第一个超链接。我不知道你是否可以只做部分字符串匹配...或者换句话说正则表达式与XPath可以吗?在这种情况下,我不想依赖于CustomerId,因为我不知道Id将是什么,因为网格是动态的。所有我关心的是抓住对网格列表中第一个超链接的引用,无论它是谁。

更新

忘了添加我正在使用Selenium Web框架的XPath。

更新

呃,刚才意识到我已经有了参考那张桌子了(虽然这里没有看到那段代码......)

所以我的做法就像grid.FindElement(By.XPath(xPath));网格引用已经是一个表元素。在这个表中是一个tbody,所以我现在尝试到这样的元素:

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

这一方也没有运气。

还根据上面的更新代码尝试了以下内容:

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

这是我试图获取超链接的页面结构

<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>someDude@gmail.com</td>
            </tr>
        .. next user, and so on
        </tbody>
    </table>
</div>

更新

试过这个,没有运气:

string xPath = (string.Format("//tbody[@id={0}]/tr/td/a(starts-with(@href, {1})", usersTableId, " /Customers/"));
OurSeleniumDriverInstance.FindElement(By.XPath(xPath ));

3 个答案:

答案 0 :(得分:3)

是的,xpath和xquery支持匹配子字符串。问题是您需要使用其中一个功能来完成它。你的xpath看起来如下(好吧,你的C#生成xpath ......):

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

这里定义了所有功能: http://www.w3schools.com/xpath/xpath_functions.asp

编辑:添加'@'表示href是一个属性。谢谢你。

编辑#2:我不知道为什么我的答案不被接受 - xpath是正确的并且有效。对我而言, a 标签不太可能是标签的子项。你错过了 tr td 标签吗?

答案 1 :(得分:3)

虽然您可以使用yajoe所示的XPath,但如果可以的话,我还建议使用LINQ to XML:

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

我更喜欢这个,因为它保留了数据&#34;零件与&#34;代码分开&#34;部分,非常类似于参数化的SQL语句。

(当然,它确实依赖于您使用.NET 3.5或更高版本。)

答案 2 :(得分:1)

您可以使用XPath starts-with功能:

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

注意您的XPath结构不正确,href是一个属性,因此需要以@符号作为前缀,以表明它位于属性轴上。