# 9N WebDriver – 定位元素:第 4a 部分(通过 xpath)
> 原文: [https://javabeginnerstutorial.com/selenium/9n-webdriver-locating-elements-4a/](https://javabeginnerstutorial.com/selenium/9n-webdriver-locating-elements-4a/)
欢迎回来,我们今天将讨论 XPath 策略。 这也是一种先进且有效的定位策略(`cssSelectors`也是!)。 虽然有效,但有时可能会造成混淆。 因此,让我们深入研究如何理解我们经常被误解的朋友,并一劳永逸地提出好的代码。
当所有希望都丧失了时,拯救自己的唯一机会就是转向 XPath 策略。 因为在大多数情况下,我们将测试现有的东西并且无法修改。 我们并不总是能够控制页面以添加一些 ID,从而使自动化成为一项更简单的任务。 因此,请停止咆哮并认真对待!
*准备开始*
**XPath** (XML 路径语言):根据 [w3schools](https://www.w3schools.com/xml/xpath_intro.asp) 的说法,XPath 是一种“路径式”语言,用于标识和浏览 XML 文档中的各种元素和属性。
因此,XPath 提供了用于定位 HTML 文档中任何元素的语法。
**注意:**
*如果到目前为止,您从未接触过 XPath,请在继续进行操作之前先了解 XPath 术语。 特别是,节点和这些节点之间的关系即父级,子级,同级,祖先,后代。*
如果您已经知道这些术语,并且希望略微刷一下,请参考下图。 礼貌: [w3schools](https://www.w3schools.com/xml/dom_intro.asp)
![xpath DOM](https://img.kancloud.cn/84/36/84365ac972b6a2b7d85d62e5fcb5ad60_1071x468.png)
现在是当今的主要任务**:通过 XPath 策略定位元素!** 在这篇文章中,我们将研究以下技术,
1. 捷径
2. 绝对 XPath 和相对 XPath
3. 使用标签和属性
4. 使用两个条件
5. 使用`contains()`
6. 查找多个元素
让我们从最简单的动机开始。
### 1.捷径:
是否想以简单的方式在网页上找到任何元素的 XPath? 做完了。是否希望几乎每次都处于完美的工作状态? 也做完了。 马上完成所有这些操作呢? 它让您涵盖了摇滚明星! 您只需要“Firebug”! 它可以作为 Firefox 浏览器的附加组件使用。
食谱来了:
1. 点击 Firebug 图标或按“`F12`”。
2. 检查其 XPath 是必需的元素。
3. 相应的代码将在 Firebug 面板的“HTML”部分中突出显示。
4. 右键点击突出显示的代码,然后选择“复制 XPath”
5. 瞧! 您已将准备好的烘焙 XPath 复制到剪贴板!
瞥见我们刚才所说的话,
![xpath firebug](https://img.kancloud.cn/5d/6a/5d6a6261186729a8fba9290d3ef521fd_580x423.png)
如果您希望获得有关 Firebug 的详细信息,[请在处查看](https://javabeginnerstutorial.com/selenium/7n-ide-using-firebug/)。
### 2.现在对于**长短**:
为了从头提出 XPath,我们首先需要了解可用的两种 Xpath。 它们是绝对 XPath 和相对 XPath。
| **绝对 XPath** | **相对 XPath** |
| --- | --- |
| 它以单个正斜杠(`/`)开头。 | 它以双正斜杠(`//`)开头。 |
| `/`指示 XPath 引擎参考根节点搜索元素。 | `//`指示 XPath 引擎在 DOM 结构中的任何位置搜索匹配的元素。 |
| 与相对的 XPath 相比,元素标识更快。 | 由于仅指定了部分路径,因此需要花费更多时间来标识元素。 |
| 即使对 HTML DOM 结构进行了最细微的更改(例如添加标签或删除标签),绝对 XPath 也会失败。 | 相对 XPath 较短,更改的可能性较小,从而使其更可靠。 |
| 例如,`/html/head/body/div[2]/form/input` | 例如`//input[@name="username"]` |
有了这些基本知识,就让我们开始吧!
### 3.使用标签和属性:
可以使用其 HTML 标签,其属性(例如 ID,名称,类,标题,值,`href`,`src`等)及其相应的值来定位特定的 Web 元素。
**语法**:`driver.findElement(By.xpath("//tag_name[@attribute='value']"));`
**解释**:标识 XPath 指向的元素。 “`//`”标识指定的节点,“`@`”符号用于选择与给定值匹配的指定属性。
**示例**:让我们在 Gmail 帐户注册页面上找到名字文本框。
右键点击“名字”文本框,然后选择检查元素,以获取相应的 HTML 代码,如下所示,
```java
<input value="" name="FirstName" id="FirstName" spellcheck="false"
class="form-error" aria-invalid="true" type="text">
```
我们可以看到“`input`”标签具有一个“`name`”属性,其值为“`FirstName`”。
*代码:*(可以使用以下任一选项)
```java
driver.findElement(By.xpath("//input[@name='FirstName']"));
driver.findElement(By.xpath("//input[@id='FirstName']"));
driver.findElement(By.xpath("//input[@class='form-error']"));
```
如果您希望使用绝对路径,
```java
driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/div[1]/div/form/div[1]/fieldset/label[1]/input"));
```
表单标签有许多子`div`标签。 在我们的情况下,我们希望选择第一个`div`标签。 可以将其指定为“`div[1]`”。 这些方括号`[]`中的数字表示要选择的确切同级。
### 4.使用两个条件
如果多个标签具有相同的属性值怎么办? 或者,如果您希望仅在元素与指定条件都匹配时才定位它,该怎么办?
**语法**:`driver.findElement(By.xpath("//tag_name[@attribute1='value1'][@attribute2='value2']"))`
**说明**:标识具有指定`tag_name`的元素,这些元素的属性与给定值匹配。
**示例**:让我们在 Gmail 帐户注册页面上找到“确认密码”文本框。
右键点击“创建密码”和“确认密码”文本框,然后选择检查元素以获取相应的 HTML 代码,如下所示,
```java
<input name="Passwd" id="Passwd" type="password">
<input name="PasswdAgain" id="PasswdAgain" type="password">
```
请注意,两个文本框的“`class`”属性值均相同,但“`id`”和“`name`”的值均不同。 因此,为了找到“确认密码”文本框,让我们同时提及其“`class`”和“`id`”值。
*代码:*
```java
driver.findElement(By.xpath("//input[@type='password'][@id='PasswdAgain']"));
```
### 5.使用`contains()`:
如今,大多数属性值(例如“`id`”,“`src`”,“`href`”等)都是使用恒定的前缀或后缀动态生成的。
想象一个网页每天都有变化的图像。 其`src`可以是“`Image_random-generated-key_date.jpg`”。 在这种情况下,我们可以通过 XPath 使用在其`src`属性中包含“`Image`”值的“`img`”标记定位图像。 因此,通过指定属性的部分值,我们可以找到元素。
**语法**:`driver.findElement(By.xpath("//tag_name[contains(@attribute, 'value')]]"))`
**说明**:标识具有指定`tag_name`的元素,该元素的属性与给定的部分值相匹配。
**示例**:让我们在 Gmail 帐户注册页面上找到“下一步”按钮。
右键单击按钮并检查元素以获取相应的 HTML 代码,如下所示,
*代码:*
```java
driver.findElement(By.xpath("//div[contains(@class,'button')]/input"));
```
注意,该 XPath 标识`div`元素,该`div`元素包含带有部分值`button`的`class`属性(`<div class="form-element nextstep-button">`),然后找到其子“`input`”标签(即“提交”按钮)。
### 6.查找多个元素
您可能会遇到希望查找具有特定类或名称的所有元素并对它们执行某些操作的情况。 星号(`*`)符号可助我们一臂之力!
**示例**:让我们在 Gmail 帐户注册页面上找到所有类值为“`goog-inline-block`”的元素。
*代码:*
```java
driver.findElements(By.xpath("//*[contains(@class,'goog-inline-block')]"));
```
这将找到在其“`class`”属性中包含值“`goog-inline-block`”的所有标签。
明确指出要使用“`findElements`”,以便将所有已标识的 Web 元素添加到列表中。 如果使用“`findElement`”,它将仅返回所标识的第一个元素。
**概览**
让我们来看一个测试案例,该案例实现了迄今为止本文中涵盖的所有技术,
*场景*
1. 打开 Firefox 浏览器。
2. 导航到 Google 帐户创建页面
3. 使用绝对 XPath 找到“名字”文本框
4. 输入“`testFirst`”作为名字
5. 使用标签和“`id`”属性找到“姓氏”文本框(当然是相对的 XPath!)
6. 输入“`testLast`”作为姓氏
7. 使用两个条件(类型和 ID 属性)找到“确认密码”文本框
8. 输入“`Pass1234!`”作为确认密码
9. 使用星号将所有包含在其“`class`”属性中值“`goog-inline-block`”的元素定位
10. 将找到的元素总数打印到控制台
11. 将第一个标识的元素的标题值打印到控制台
12. 使用`contains()`找到“下一步”按钮
13. 将其“`name`”属性的值打印到控制台
14. 验证 Eclipse IDE 控制台的输出屏幕和 JUnit 窗格是否成功
此方案的 JUnit 代码是,
```java
package com.blog.junitTests;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver;
public class ElementLocatorTest4 {
//Declaring variables
private WebDriver driver;
private String baseUrl;
@Before
public void setUp() throws Exception{
// Selenium version3 beta releases require system property set up
System.setProperty("webdriver.gecko.driver", "E:\\ Softwares\\Selenium\\geckodriver-v0.10.0-win64\\geckodriver.exe");
// Create a new instance for the class FirefoxDriver
// that implements WebDriver interface
driver = new FirefoxDriver();
// Implicit wait for 5 seconds
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
// Assign the URL to be invoked to a String variable
baseUrl = "https://accounts.google.com/SignUp";
}
@Test
public void testPageTitle() throws Exception{
// Open baseUrl in Firefox browser window
driver.get(baseUrl);
// Locate 'First Name' text box by absolute XPath
// assign it to a variable of type WebElement
WebElement firstName = driver.findElement(By.xpath("/html/body/div[1]/div[2]/div/div[1]"
+ "/div/form/div[1]/fieldset/label[1]/input"));
// Clear the default placeholder or any value present
firstName.clear();
// Enter/type the value to the text box
firstName.sendKeys("testFirst");
// Locate 'Last Name' text box by relative XPath: using tag and id attribute
WebElement lastName = driver.findElement(By.xpath("//input[@id='LastName']"));
lastName.clear();
lastName.sendKeys("testLast");
// Locate 'Confirm your password' text box by XPath: using two conditions
WebElement confirmPwd = driver.findElement(By.xpath("//input[@type='password'][@id='PasswdAgain']"));
confirmPwd.clear();
confirmPwd.sendKeys("Pass1234!");
//Locate all elements with class 'goog-inline-block' by relative XPath: using asterisk symbol
List<WebElement> dropdowns = driver.findElements(By.xpath("//*[contains(@class,'goog-inline-block')]"));
// Prints to the console, the total number of elements located
System.out.println("Total elements containing the class 'goog-inline-block' are= " + dropdowns.size());
// Prints first identified element's title value to console
System.out.println("Value of the dropdown's 'title' attribute = " + dropdowns.get(0).getAttribute("title"));
// Locate 'Next step' button by XPath: contains() and child element
WebElement submitBtn = driver.findElement(By.xpath("//div[contains(@class,'button')]/input"));
// Prints submitBtn's 'name' attribute's value to the console
System.out.println("Value of the button's 'name' attribute = " + submitBtn.getAttribute("name"));
}
@After
public void tearDown() throws Exception{
// Close the Firefox browser
driver.close();
}
}
```
*执行结果:*
这段代码将作为本文讨论的每种技术的一部分进行解释。
在 JUnit 窗口中,绿色条显示测试用例已成功执行。 控制台窗口显示没有任何错误。 它还显示带有星号的 Web 元素总数,以及下拉菜单和按钮的属性值。
![xpath console output](https://img.kancloud.cn/12/a2/12a26332bc0c63444798dbd1fd74c25b_706x335.png)
下图显示了成功执行测试脚本后获得的 Firefox 输出。
![xpath firefox output](https://img.kancloud.cn/d4/83/d48327bae38e910ea811958848a6cc8a_504x364.png)
休息一下伙计! 我们的下一篇文章将是定位元素策略的最后一篇。 所以不要错过! 很快见,祝您愉快!
- JavaBeginnersTutorial 中文系列教程
- Java 教程
- Java 教程 – 入门
- Java 的历史
- Java 基础知识:Java 入门
- jdk vs jre vs jvm
- public static void main(string args[])说明
- 面向初学者的 Java 类和对象教程
- Java 构造器
- 使用 Eclipse 编写 Hello World 程序
- 执行顺序
- Java 中的访问修饰符
- Java 中的非访问修饰符
- Java 中的数据类型
- Java 中的算术运算符
- Java 语句初学者教程
- 用 Java 创建对象的不同方法
- 内部类
- 字符串构建器
- Java 字符串教程
- Java 教程 – 变量
- Java 中的变量
- Java 中的局部变量
- Java 中的实例变量
- Java 引用变量
- 变量遮盖
- Java 教程 – 循环
- Java for循环
- Java 教程 – 异常
- Java 异常教程
- 异常处理 – try-with-resources语句
- Java 异常处理 – try catch块
- Java 教程 – OOPS 概念
- Java 重载
- Java 方法覆盖
- Java 接口
- 继承
- Java 教程 – 关键字
- Java 中的this关键字
- Java static关键字
- Java 教程 – 集合
- Java 数组教程
- Java 集合
- Java 集合迭代器
- Java Hashmap教程
- 链表
- Java 初学者List集合教程
- Java 初学者的Map集合教程
- Java 初学者的Set教程
- Java 初学者的SortedSet集合教程
- Java 初学者SortedMap集合教程
- Java 教程 – 序列化
- Java 序列化概念和示例
- Java 序列化概念和示例第二部分
- Java 瞬态与静态变量
- serialVersionUID的用途是什么
- Java 教程 – 枚举
- Java 枚举(enum)
- Java 枚举示例
- 核心 Java 教程 – 线程
- Java 线程教程
- Java 8 功能
- Java Lambda:初学者指南
- Lambda 表达式简介
- Java 8 Lambda 列表foreach
- Java 8 Lambda 映射foreach
- Java 9
- Java 9 功能
- Java 10
- Java 10 独特功能
- 核心 Java 教程 – 高级主题
- Java 虚拟机基础
- Java 类加载器
- Java 开发人员必须知道..
- Selenium 教程
- 1 什么是 Selenium?
- 2 为什么要进行自动化测试?
- 3 Selenium 的历史
- 4 Selenium 工具套件
- 5 Selenium 工具支持的浏览器和平台
- 6 Selenium 工具:争霸
- 7A Selenium IDE – 简介,优点和局限性
- 7B Selenium IDE – Selenium IDE 和 Firebug 安装
- 7C Selenium IDE – 突破表面:初探
- 7D Selenium IDE – 了解您的 IDE 功能
- 7E Selenium IDE – 了解您的 IDE 功能(续)。
- 7F Selenium IDE – 命令,目标和值
- 7G Selenium IDE – 记录和运行测试用例
- 7H Selenium IDE – Selenium 命令一览
- 7I Selenium IDE – 设置超时,断点,起点
- 7J Selenium IDE – 调试
- 7K Selenium IDE – 定位元素(按 ID,名称,链接文本)
- 7L Selenium IDE – 定位元素(续)
- 7M Selenium IDE – 断言和验证
- 7N Selenium IDE – 利用 Firebug 的优势
- 7O Selenium IDE – 以所需的语言导出测试用例
- 7P Selenium IDE – 其他功能
- 7Q Selenium IDE – 快速浏览插件
- 7Q Selenium IDE – 暂停和反射
- 8 给新手的惊喜
- 9A WebDriver – 架构及其工作方式
- 9B WebDriver – 在 Eclipse 中设置
- 9C WebDriver – 启动 Firefox 的第一个测试脚本
- 9D WebDriver – 执行测试
- 9E WebDriver – 用于启动其他浏览器的代码示例
- 9F WebDriver – JUnit 环境设置
- 9G WebDriver – 在 JUnit4 中运行 WebDriver 测试
- 9H WebDriver – 隐式等待
- 9I WebDriver – 显式等待
- 9J WebDriver – 定位元素:第 1 部分(按 ID,名称,标签名称)
- 9K WebDriver – 定位元素:第 2 部分(按className,linkText,partialLinkText)
- 9L WebDriver – 定位元素:第 3a 部分(按cssSelector定位)
- 9M WebDriver – 定位元素:第 3b 部分(cssSelector续)
- 9N WebDriver – 定位元素:第 4a 部分(通过 xpath)
- 9O WebDriver – 定位元素:第 4b 部分(XPath 续)
- 9P WebDriver – 节省时间的捷径:定位器验证
- 9Q WebDriver – 处理验证码
- 9R WebDriver – 断言和验证
- 9S WebDriver – 处理文本框和图像
- 9T WebDriver – 处理单选按钮和复选框
- 9U WebDriver – 通过两种方式选择项目(下拉菜单和多项选择)
- 9V WebDriver – 以两种方式处理表
- 9W WebDriver – 遍历表元素
- 9X WebDriver – 处理警报/弹出框
- 9Y WebDriver – 处理多个窗口
- 9Z WebDriver – 最大化窗口
- 9AA WebDriver – 执行 JavaScript 代码
- 9AB WebDriver – 使用动作类
- 9AC WebDriver – 无法轻松定位元素? 继续阅读...
- 10A 高级 WebDriver – 使用 Apache ANT
- 10B 高级 WebDriver – 生成 JUnit 报告
- 10C 高级 WebDriver – JUnit 报表自定义
- 10D 高级 WebDriver – JUnit 报告自定义续
- 10E 高级 WebDriver – 生成 PDF 报告
- 10F 高级 WebDriver – 截屏
- 10G 高级 WebDriver – 将屏幕截图保存到 Word 文档
- 10H 高级 WebDriver – 发送带有附件的电子邮件
- 10I 高级 WebDriver – 使用属性文件
- 10J 高级 WebDriver – 使用 POI 从 excel 读取数据
- 10K 高级 WebDriver – 使用 Log4j 第 1 部分
- 10L 高级 WebDriver – 使用 Log4j 第 2 部分
- 10M 高级 WebDriver – 以无头模式运行测试
- Vue 教程
- 1 使用 Vue.js 的 Hello World
- 2 模板语法和反应式的初探
- 3 Vue 指令简介
- 4 Vue Devtools 设置
- 5 数据绑定第 1 部分(文本,原始 HTML,JavaScript 表达式)
- 6 数据绑定第 2 部分(属性)
- 7 条件渲染第 1 部分(v-if,v-else,v-else-if)
- 8 条件渲染第 2 部分(v-if和v-show)
- 9 渲染列表第 1 部分(遍历数组)
- 10 渲染列表第 2 部分(遍历对象)
- 11 监听 DOM 事件和事件修饰符
- 12 监听键盘和鼠标事件
- 13 让我们使用简写
- 14 使用v-model进行双向数据绑定
- 15 表单输入绑定
- 18 类绑定
- Python 教程
- Python 3 简介
- Python 基础知识 - 又称 Hello World 以及如何实现
- 如何在 Windows 中安装 python
- 适用于 Windows,Mac,Linux 的 Python 设置
- Python 数字和字符串
- Python 列表
- Python 集
- Python 字典
- Python 条件语句
- Python 循环
- Python 函数
- 面向对象编程(OOP)
- Python 中的面向对象编程
- Python 3 中的异常处理
- Python 3:猜数字
- Python 3:猜数字 – 回顾
- Python 生成器
- Hibernate 教程
- Hibernate 框架基础
- Hibernate 4 入门教程
- Hibernate 4 注解配置
- Hibernate 4 的实体关系
- Hibernate 4 中的实体继承模型
- Hibernate 4 查询语言
- Hibernate 4 数据库配置
- Hibernate 4 批处理
- Hibernate 4 缓存
- Hibernate 4 审计
- Hibernate 4 的并发控制
- Hibernate 4 的多租户
- Hibernate 4 连接池
- Hibernate 自举