Chọn một lớp css với xpath


87

Tôi chỉ muốn chọn một lớp riêng có tên là .date

Vì một số lý do, tôi không thể làm cho nó hoạt động. Nếu có ai biết điều gì sai với mã của tôi, nó sẽ được đánh giá cao.

@$doc = new DOMDocument();
@$doc->loadHTML($html);
$xml = simplexml_import_dom($doc); // just to make xpath more simple
$images = $xml->xpath('//[@class="date"]');                             
foreach ($images as $img)
{
    echo  $img." ";
}

2
và những gì về phần html? (Thích để hiển thị đầu ra chúng tôi SimpleXML từ asXML () vì nó là gần với xpath)
SergeS

nếu có nhiều lớp bạn cần làmcontains(@class, 'date')
Gordon



Câu trả lời của @ Gordon là nguy hiểm, nếu thuộc tính lớp là "datetime" thì nó cũng sẽ khớp. câu trả lời của user716736 là đầy đủ hơn.
Niels Bom

Câu trả lời:


242

Tôi muốn viết câu trả lời chính tắc cho câu hỏi này vì câu trả lời ở trên có vấn đề.

Vấn đề của chúng ta

Bộ chọn CSS :

.foo

sẽ chọn bất kỳ phần tử nào có lớp foo .

Làm thế nào để bạn làm điều này trong XPath?

Mặc dù XPath mạnh hơn CSS, XPath không có công cụ chọn lớp CSS tương đương với bản gốc . Tuy nhiên, có một giải pháp.

Đúng cách để làm điều đó

Bộ chọn tương đương trong XPath là:

//*[contains(concat(" ", normalize-space(@class), " "), " foo ")]

Hàm normalize-space dải khoảng trắng đầu và cuối (và cũng thay thế chuỗi ký tự khoảng trắng bằng một khoảng trắng).

(Theo nghĩa chung hơn) đây cũng tương đương với bộ chọn CSS:

*[class~="foo"]

sẽ khớp với bất kỳ phần tử nào có giá trị thuộc tính lớp là danh sách các giá trị được phân tách bằng khoảng trắng, một trong số đó chính xác bằng foo .

Một vài cách hiển nhiên, nhưng sai để làm điều đó

Bộ chọn XPath:

//*[@class="foo"]

không hoạt động! vì nó sẽ không khớp với một phần tử có nhiều hơn một lớp, chẳng hạn

<div class="foo bar">

Nó cũng sẽ không khớp nếu có thêm bất kỳ khoảng trắng nào xung quanh tên lớp:

<div class="  foo ">

Bộ chọn XPath 'cải tiến'

//*[contains(@class, "foo")]

cũng không hoạt động! vì nó đối sánh sai các phần tử với foobar lớp , chẳng hạn

<div class="foobar">

Tín dụng thuộc về anh bạn này, người là giải pháp được công bố sớm nhất cho vấn đề này mà tôi tìm thấy trên web: http://dubinko.info/blog/2007/10/01/simple-parsing-of-space-seprated-attributes- in-xpathxslt /


Cần phải chuẩn hóa không gian là gì?
Freek

"câu trả lời ở trên" có lẽ là của MrGlass.
LarsH

Điều này có khả thi <div class="foo\tbar">không? Ý tôi là, các tên lớp được phân tách bằng một tab.
Frozen Flame

1
nhưng <div class = "group-condition" /> và <div class = "condition" /> là giống nhau đối với $ x ('// div [chứa (concat ("", normalize-space (@class), " ")," điều kiện ")] ')
Memke

1
@ testerjoe2 bạn đã thử //*[contains(concat(" ", normalize-space(@class), " "), " foo ")]chưa?
Niels Bom

11

//[@class="date"] không phải là một xpath hợp lệ.

Hãy thử //*[@class="date"], hoặc nếu bạn biết đó là một hình ảnh,//img[@class="date"]


7

XPath 3.1 giới thiệu một hàm chứa mã thông báo và do đó cuối cùng đã giải quyết được điều này 'chính thức'. Nó được thiết kế để hỗ trợ các lớp học .

Thí dụ:

//*[contains-token(@class, "foo")]

Chức năng này đảm bảo rằng khoảng trắng (không chỉ (U + 0020)) được xử lý chính xác, hoạt động trong trường hợp lặp lại tên lớp và thường bao gồm các trường hợp cạnh.


Lưu ý: Tính đến ngày hôm nay (13-12-2016) XPath 3.1 có trạng thái Đề xuất Ứng viên .


Nó không hoạt động trong chrome mới nhất hiện nay. Cho đến khi nó hoạt động, làm thế nào để chúng ta có được xung quanh giới hạn đó // * [chứa (@class, "foo")] cũng sẽ chọn bất kỳ lớp học có chứa foo, chẳng hạn như foobar, Fooz, vv
MasterJoe


1

HTML cho phép tên phần tử và thuộc tính không phân biệt chữ hoa chữ thường và sau đó lớp là danh sách tên lớp được phân tách bằng dấu cách. Ở đây chúng tôi đi tìm một imgthẻ và classtên date:

//*['IMG' = translate(name(.), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')]/@*['CLASS' = translate(name(.), 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ') and contains(concat(' ', normalize-space(.), ' '), concat(' ', 'date', ' '))]

Xem thêm: Chuyển đổi CSS Selector sang XPath


1

CẨN THẬN CÁC DẤU HIỆU MINUS TRONG TEMPLATE !!! Nếu bạn đang truy vấn "my-ownclass" trong DOM:

<ul class="my-ownclass"><li>...</li></ul>
<ul class="someother"><li>...</li></ul>
<ul><li>...</li></ul>

$finder = new DomXPath($dom);
$nodes = $finder->query(".//ul[contains(@class, 'my-ownclass')]"); // This will NOT behave as expected! This will strangely match all the <ul> elements in DOM.
$nodes = $finder->query(".//ul[contains(@class, 'ownclass')]"); // This will match the element.
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.