Các đầu câu trả lời hiện bởi tokland chỉ hoạt động trên các nút văn bản và không trên các nút với các yếu tố khác bên trong.
Câu trả lời ngắn
Biểu thức XPath này sẽ truy vấn một nút có chứa văn bản "Văn bản nút":
const [button] = await page.$x("//button[contains(., 'Button text')]");
if (button) {
await button.click();
}
Để tôn trọng <div class="elements">
xung quanh các nút, hãy sử dụng mã sau:
const [button] = await page.$x("//div[@class='elements']/button[contains(., 'Button text')]");
Giải trình
Để giải thích tại sao việc sử dụng nút văn bản ( text()
) là sai trong một số trường hợp, hãy xem một ví dụ:
<div>
<button>Start End</button>
<button>Start <em>Middle</em> End</button>
</div>
Đầu tiên, hãy kiểm tra kết quả khi sử dụng contains(text(), 'Text')
:
//button[contains(text(), 'Start')]
sẽ trả về cả hai nút (như mong đợi)
//button[contains(text(), 'End')]
sẽ chỉ trả về một nút (nút đầu tiên) như text()
trả về danh sách có hai văn bản ( Start
và End
), nhưng contains
sẽ chỉ kiểm tra nút đầu tiên
//button[contains(text(), 'Middle')]
sẽ không trả về kết quả vì text()
không bao gồm văn bản của các nút con
Dưới đây là các biểu thức XPath cho contains(., 'Text')
, hoạt động trên chính phần tử bao gồm các nút con của nó:
//button[contains(., 'Start')]
sẽ trả về cả hai nút
//button[contains(., 'End')]
sẽ trả lại cả hai nút
//button[contains(., 'Middle')]
sẽ trả lại một (nút cuối cùng)
Vì vậy, trong hầu hết các trường hợp, sẽ hợp lý hơn nếu sử dụng .
thay vì text()
trong biểu thức XPath.