2010-02-01 18 views

Trả lời

52

Nếu bạn dịch "không phải là hậu duệ" thành "không có tổ tiên", bạn sẽ nhận được biểu thức //*[not(ancestor::X)]. Điều này sẽ trả về tất cả các nút trong một tài liệu, mà không phải là con cháu của các nút có tên là "X".

16

jarnbjo chỉ ra cách trực quan để thực hiện việc này, sử dụng //*[not(ancestor::X)]. Điều này có thành tích rất lớn là nó sẽ làm việc không phân biệt như thế nào tài liệu của bạn được cấu trúc, và đó là những gì bạn nên sử dụng trong hầu hết các trường hợp.

Nhưng nếu bạn có tài liệu rất lớn, nó có thể cực kỳ không hiệu quả. Đó là một truy vấn thực sự tốn kém. Nó cho bộ xử lý XPath truy cập mọi nút trong tài liệu và kiểm tra nút tổ tiên của nó cho sự hiện diện của một phần tử có tên X. Trong khi có thể bộ xử lý XPath đủ thông minh để biết rằng nó không cần truy cập vào con cháu của X để đánh giá truy vấn đó, điều đó không có khả năng.

Nếu bạn có một số thông tin về vị trí phần tử X và bạn cẩn thận, bạn có thể viết truy vấn hiệu quả hơn. Ví dụ, nếu X là một đứa trẻ của phần tử cấp cao nhất, và nó có rất nhiều con cháu, đây sẽ là nhanh hơn nhiều:

/* | /*/* | /*/*[not(name()='X')]//* 

Đó tìm thấy các yếu tố cấp cao nhất, tất cả các trẻ em ngay lập tức của nó, và hậu duệ của bất kỳ đứa con ngay lập tức nào của nó không được đặt tên X. Nó sẽ không kiểm tra bất kỳ hậu duệ của X.

Tương tự như vậy, nếu bạn biết rằng X là gần với đáy của cây, truy vấn này có thể hiệu quả hơn:

//*[not(ancestor::*[position() <= 3][X])] 

bởi vì nó sẽ không kiểm tra toàn bộ trục tổ tiên cho mỗi nút nó kiểm tra, chỉ ba yếu tố cuối cùng của nó. (Trừ khi bộ xử lý XPath đủ ngu ngốc để kiểm tra mọi nút trên trục khi nó thực hiện các thử nghiệm sử dụng position(), có thể là vậy.)

Như tôi đã nói, hầu hết thời gian phiên bản đơn giản nhất sẽ là tốt nhất, và hầu hết thời gian đó là những gì tôi muốn sử dụng bản thân mình.

Các vấn đề liên quan