Sử dụng XPATH để tìm kiếm văn bản chứa & nbsp;


120

Tôi sử dụng Trình duyệt XPather để kiểm tra các biểu thức XPATH của mình trên trang HTML.

Mục tiêu cuối cùng của tôi là sử dụng các biểu thức này trong Selenium để kiểm tra các giao diện người dùng của tôi.

Tôi nhận được một tệp HTML có nội dung tương tự như sau:

<tr>
  <td> abc </td>
  <td> & nbsp; </td>
</tr>

Tôi muốn chọn một nút có văn bản chứa chuỗi " &nbsp;".

Với một chuỗi bình thường như "abc" thì không có vấn đề gì. Tôi sử dụng một XPATH tương tự như //td[text()="abc"].

Khi tôi thử với XPATH như thể //td[text()="&nbsp;"]nó không trả về gì. Có quy tắc đặc biệt nào liên quan đến văn bản có " &" không?


Chuyển đổi XSL thực tế của bạn không trả lại gì? Hay chỉ có Xpather?
Zack The Human

Câu trả lời:


89

Có vẻ như OpenQA , những người đứng sau Selenium, đã giải quyết vấn đề này. Họ đã xác định một số biến để đối sánh rõ ràng các khoảng trắng. Trong trường hợp của tôi, tôi cần sử dụng XPATH tương tự như //td[text()="${nbsp}"].

Tôi đã sao chép ở đây văn bản từ OpenQA liên quan đến vấn đề này (tìm thấy ở đây ):

HTML tự động chuẩn hóa khoảng trắng trong các phần tử, bỏ qua các khoảng trắng ở đầu / cuối và chuyển đổi các khoảng trắng, tab và dòng mới thành một khoảng trắng duy nhất. Khi Selenium đọc văn bản ra khỏi trang, nó sẽ cố gắng sao chép hành vi này, vì vậy bạn có thể bỏ qua tất cả các tab và dòng mới trong HTML của mình và thực hiện các xác nhận dựa trên giao diện của văn bản trong trình duyệt khi được hiển thị. Chúng tôi thực hiện việc này bằng cách thay thế tất cả khoảng trắng không hiển thị (bao gồm cả khoảng trắng không ngắt " &nbsp;") bằng một khoảng trắng duy nhất. Tất cả các dòng mới có thể nhìn thấy ( <br>, <p><pre>định dạng dòng mới) cần được bảo tồn.

Chúng tôi sử dụng cùng một logic chuẩn hóa trên văn bản của các bảng trường hợp kiểm tra HTML Selenese. Điều này có một số lợi thế. Đầu tiên, bạn không cần phải nhìn vào nguồn HTML của trang để tìm ra những xác nhận của bạn; Các &nbsp;ký hiệu "" không hiển thị đối với người dùng cuối và vì vậy bạn không cần phải lo lắng về chúng khi viết các bài kiểm tra Selenese. (Bạn không cần đặt &nbsp;các điểm đánh dấu "" trong trường hợp thử nghiệm của mình để khẳng định Văn bản trên trường có chứa " &nbsp;".) Bạn cũng có thể đặt thêm các dòng mới và khoảng trắng trong các <td>thẻ Selenese của mình ; vì chúng tôi sử dụng cùng một logic chuẩn hóa trên trường hợp thử nghiệm như chúng tôi làm trên văn bản, chúng tôi có thể đảm bảo rằng các xác nhận và văn bản được trích xuất sẽ khớp chính xác.

Điều này tạo ra một chút vấn đề trong những trường hợp hiếm hoi khi bạn thực sự muốn / cần chèn thêm khoảng trắng trong trường hợp thử nghiệm của mình. Ví dụ: bạn có thể cần nhập văn bản vào trường như sau: " foo ". Nhưng nếu bạn chỉ viết <td>foo </td>trong trường hợp kiểm tra Selenese của mình, chúng tôi sẽ thay thế các khoảng trắng thừa của bạn chỉ bằng một khoảng trắng.

Vấn đề này có một cách giải quyết đơn giản. Chúng tôi đã xác định một biến trong Selenese ${space}, có giá trị là một khoảng trắng. Bạn có thể sử dụng ${space}để chèn một không gian đó sẽ không được tự động cắt, như thế này: <td>foo${space}${space}${space}</td>. Chúng tôi cũng đã bao gồm một biến ${nbsp}mà bạn có thể sử dụng để chèn một khoảng trắng không ngắt.

Lưu ý rằng XPath không chuẩn hóa khoảng trắng theo cách chúng ta làm. Nếu bạn cần phải viết một XPath như //div[text()="hello world"]nhưng HTML của liên kết thực sự là " hello&nbsp;world", bạn sẽ cần phải chèn một thực tế " &nbsp;" vào trường hợp thử nghiệm Selenese của bạn để làm cho nó phù hợp, như thế này: //div[text()="hello${nbsp}world"].


1
Liên kết OpenQA không tải thành công nữa
kjosh

1
Tôi chỉ muốn lưu ý rằng $ {nbsp} không hoạt động đối với tôi trong các công cụ dành cho nhà phát triển Selenium hoặc Chrome \u00a0. Điều hiệu quả với tôi là gõ một khoảng trắng không ngắt, trên mac Alt+Shift+Space. Tìm kiếm trên web cho biết Alt+0160trên cửa sổ.
Cynic

25

Tôi thấy mình có thể khớp khi nhập khoảng trắng không ngắt được mã hóa cứng (U + 00A0) bằng cách gõ Alt + 0160 trên Windows giữa hai dấu ngoặc kép ...

//table[@id='TableID']//td[text()=' ']

đã làm việc cho tôi với char đặc biệt.

Theo những gì tôi hiểu, tiêu chuẩn XPath 1.0 không xử lý các ký tự Unicode thoát. Dường như có các chức năng cho điều đó trong XPath 2.0 nhưng có vẻ như Firefox không hỗ trợ nó (hoặc tôi hiểu nhầm điều gì đó). Vì vậy, bạn phải làm với codepage cục bộ. Tôi biết.

Trên thực tế, có vẻ như tiêu chuẩn đang dựa vào ngôn ngữ lập trình sử dụng XPath để cung cấp trình tự thoát Unicode chính xác ... Vì vậy, bằng cách nào đó, tôi đã làm đúng.


Sử dụng Xpather 1.4.1 trong Firefox 2, // td [text () = ''] không mang lại kết quả.
Zack The Human

Lấy làm tiếc. Nó không hiệu quả với tôi. Mục tiêu cuối cùng của tôi là sử dụng nó trong Selenium để kiểm tra các giao diện Web của tôi. Bản thân Selenium giữ các biểu thức kiểm tra trong một cấu trúc XML và việc gõ phím Alt Windows dường như bị mất. Ngoài ra, & # 160; trả về dưới dạng một trong XML.
Bergeroy 29/10/08

Zack, như tôi đã viết, bạn phải thay thế khoảng trắng giữa hai dấu ngoặc kép bằng ký tự được tạo bởi Alt + 0160 (trên bàn phím số).
PhiLho 30/10/08

4
Got để làm việc này với PHP thành công cũng như:$col = $xpath->query("//p[text()=\"\xC2\xA0\"]");
hakre

@Bergory Điều này hoạt động bằng cách sử dụng Thước đo góc với trình điều khiển Selenium
Damian Green

4

Hãy thử sử dụng thực thể thập phân &#160;thay vì thực thể được đặt tên. Nếu điều đó không hiệu quả, bạn có thể chỉ cần sử dụng ký tự unicode cho khoảng trắng không ngắt thay vì &nbsp;thực thể.

(Lưu ý: Tôi đã không thử điều này trong XPather, nhưng tôi đã thử nó trong Oxy.)


2

Ghi nhớ rằng một bộ xử lý XML tiêu chuẩn tuân thủ sẽ thay thế bất kỳ tham chiếu thực thể khác hơn năm những tiêu chuẩn XML ( &amp;, &gt;, &lt;, &apos;, &quot;) với nhân vật tương ứng trong mã hóa mục tiêu vào thời điểm các biểu thức XPath được đánh giá. Với hành vi đó, các đề xuất của PhiLho và jsulak là cách tốt nhất nếu bạn muốn làm việc với các công cụ XML. Khi bạn nhập &#160;biểu thức XPath, nó phải được chuyển đổi thành chuỗi byte tương ứng trước khi biểu thức XPath được áp dụng.


1
Không phải nếu bạn thử / sử dụng XPath trong XPather (GUI) hoặc trong JavaScript (không tự động thay thế các thực thể, vì chúng tôi không sử dụng XML). Lời khuyên hữu ích trong các môi trường XML khác (XSTL?).
PhiLho 30/10/08

1

Tôi không thể nhận được kết quả phù hợp bằng Xpather, nhưng cách sau đây đã hoạt động với tôi với các tệp XML và XSL thuần túy trong XML Notepad của Microsoft:

<xsl:value-of select="count(//td[text()='&nbsp;'])" />

Giá trị trả về là 1, là giá trị chính xác trong trường hợp thử nghiệm của tôi.

Tuy nhiên, tôi đã phải khai báo nbsp như một thực thể trong XML và XSL của mình bằng cách sử dụng như sau:

<!DOCTYPE xsl:stylesheet [ <!ENTITY nbsp "&#160;"> ]>

Tôi không chắc điều đó có giúp được bạn không, nhưng tôi thực sự có thể tìm thấy nbsp bằng cách sử dụng biểu thức XPath.

Chỉnh sửa: Mẫu mã của tôi thực sự chứa các ký tự '& nbsp;' nhưng phần đánh dấu cú pháp JavaScript sẽ chuyển nó thành ký tự khoảng trắng. Đừng lầm lạc!


Bạn có thể chỉnh sửa mẫu mã của mình giống như đã được thực hiện cho mẫu trong câu hỏi của tôi. Thay thế thực thể nbsp của bạn bằng & amp; nbsp ;.
Bergeroy 29/10/08

1

Tìm kiếm &nbsp;hoặc chỉ nbsp- bạn đã thử cái này chưa?


Tôi nhận ra rằng điều này sẽ hoạt động nhưng không chắc chắn về những gì tôi tìm thấy. Phải có một cách trong XPATH để mã hóa một cách nhất định phù hợp với những gì tôi đang tìm kiếm.
Bergeroy 29/10/08

Có lẽ tôi nên xem xét một biểu thức chính quy.
Bergeroy 29/10/08

1

Theo HTML bạn đã cung cấp:

<tr>
  <td>abc</td>
  <td>&nbsp;</td>
</tr>

Để xác định vị trí nút bằng chuỗi, &nbsp;bạn có thể sử dụng một trong hai cách sau giải pháp dựa trên:

  • Sử dụng text():

    "//td[text()='\u00A0']"
  • Sử dụng contains():

    "//td[contains(., '\u00A0')]"

Tuy nhiên, lý tưởng nhất là bạn có thể muốn tránh ký tự KHÔNG GIAN BẮT ĐẦU và sử dụng một trong các Chiến lược định vị sau:

  • Sử dụng <tr>nút cha và following-sibling:

    "//tr//following-sibling::td[2]"
  • Sử dụng starts-with():

    "//tr//td[last()]"
  • Sử dụng <td>nút kế tiếp và nút anh chị em followingnode andsau đây`:

    "//td[text()='abc']//following::td[1]"

Tài liệu tham khảo

Bạn có thể tìm thấy một cuộc thảo luận chi tiết có liên quan trong:


tl; dr

Ký tự Unicode 'KHÔNG GIAN NGẮT' (U + 00A0)


Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.