2009-05-21 39 views
9

tôi đã xem xét câu hỏi này: Select first instance only with XPath?Chọn kết quả đầu tiên trong XPath

Nhưng nếu tôi có một nút thiết lập như thế này:


<container value=""> 
    <data id="1"></data> 
    <data id="2">test</data> 
    <container> 
    <data id="1">test</data> 
    <data id="3">test</data> 
    </container> 
</container> 

Bây giờ kịch bản của tôi được rằng đây node-set là sâu bên trong một tài liệu và tôi có một con trỏ đến vùng chứa bên trong. Vì vậy, tôi phải tiền tố XPath của tôi với "/ container/container" (đường dẫn thực sự là dài hơn, nhưng đối với ví dụ này nên làm).

EDIT: Điều tôi muốn là nút "dữ liệu" có id là 1, phải đến từ nút thấp nhất trước tiên hoặc tổ tiên gần nhất. Vì vậy, nếu tôi không thể tìm thấy nó trên "hiện tại" (/ container/container), tôi nên nhìn vào tổ tiên và có được một trong những gần nhất (hoặc cuối cùng, không tìm thấy bất cứ điều gì). Tôi đã cố gắng này:

/container/container/tổ tiên-or-self :: container/dữ liệu [@ id = "1"]

nào mang lại kết quả thiết lập với hai nút. Tôi nghĩ rằng tôi có thể sử dụng last() để có được một sâu nhất, vì vậy tôi tacked rằng vào cuối, nhưng vô ích.

+0

Các đặc điểm kỹ thuật có thể làm một cách rõ ràng hơn. Bạn muốn nút dữ liệu? Nút dữ liệu phải có id là 1? Hình thành vùng chứa ban đầu nếu nút dữ liệu không có id là 1 bạn muốn di chuyển tài liệu lên vùng chứa chính để xem liệu có nút dữ liệu có id là 1 hay không, nếu không tiếp tục cho đến khi nút dữ liệu có id của 1 được tìm thấy. Điều đó mô tả nó? – AnthonyWJones

+0

Tôi đã cố gắng để mô tả những gì tôi đang tìm kiếm một chút rõ ràng hơn, mặc dù một số đoán nó. Lấy làm tiếc! –

Trả lời

5

Làm thế nào bạn thử tacking cuối cùng() trên? Tôi nghĩ rằng điều này sẽ làm việc:

/container/container/ancestor-or-self::container/data[@id="1"][last()] 

EDIT:

Phải, tất nhiên, tôi quên ngoặc:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()] 

Mà làm này giống như một trong những câu trả lời khác; Tuy nhiên, như các poster ban đầu chỉ ra, biểu hiện này không thành công trên:

<container value=""> 
    <container> 
    <data id="1">a3</data> 
    <data id="3">a4</data> 
    </container> 
    <data id="1">a1</data> 
    <data id="2">a2</data> 
</container> 

Đúng như tinh thần của stackoverflow, tôi tuy nhiên có thể kết hợp câu trả lời của tôi với một trong những câu trả lời khác và nhận được một cái gì đó mà làm việc trong mọi trường hợp:

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"] 

Bằng cách này, nếu có nhiều @ id-is-1 < dữ liệu> con của một vùng chứa, điều này sẽ trả về tất cả.Để trở về chỉ có như vậy < dữ liệu> yếu tố đầu tiên:

(/container/container/ancestor-or-self::container[data[@id="1"]])[last()]/data[@id="1"][1] 
+0

Nếu đọc của tôi ở đây trên kết quả mong muốn là chính xác (lớn nếu) điều này sẽ không hoạt động vì cuối cùng() sẽ khớp trên cả hai nhánh của tổ tiên hoặc tự - đó là vấn đề thực sự, vì vậy bạn cần phải clip kết quả thiết lập hoặc sớm (như tôi có) hoặc muộn (như Dave không). – annakata

+0

Điều này thực hiện điều đó. Cảm ơn rất nhiều (tất cả mọi người)! –

1

Tôi không phải 100% rõ ràng về những gì bạn đang yêu cầu, nhưng nếu tôi đọc đúng có thể bạn chỉ muốn:

/container/container/ancestor-or-self::container[1]/data[@id='1'] 

lưu ý các "[1]"

Chỉnh sửa: suy nghĩ về nó nhiều hơn một chút và dưới đây hoạt động cho tôi đối với tất cả các trường hợp cho đến nay tìm kiếm @ id = $ N

/container/container/ancestor-or-self::container[data[@id=$N]][1]/data[@id=$N] 

Khá xpathing ngay tại đó. Về cơ bản những gì xảy ra là nodeet từ tổ tiên hoặc tự trả về thứ tự thấp nhất ở vị trí 1 - đó là thứ bạn muốn - nhưng bạn cần đặt điều kiện thứ hai vào nút đó cũng có nút dữ liệu mà bạn quan tâm, một khi bạn đã đáp ứng các điều kiện đó, bạn có nút đúng ngay bây giờ bạn chỉ muốn thêm đường hầm vào dữ liệu thực tế.

99% thời gian xpath được dễ dàng hơn nếu bạn lấy nó ra và nghĩ về nó như một thuật toán :)

+0

Tôi đã thử điều đó, nhưng điều đó không bao gồm mọi trường hợp. Điều gì sẽ xảy ra nếu tôi tìm kiếm thay vì @ id = '2'? Tôi muốn ưu tiên các kết quả từ nút hiện tại trước tổ tiên, nhưng có thể dự phòng. –

+0

Xem chỉnh sửa: Tôi tin rằng bao gồm tất cả các trường hợp được liệt kê – annakata

0

Thay vì

@id="1" 

bạn đã thử:

position() == 1 
+0

Nếu vị trí() == 1 sẽ hoạt động thì chỉ cần thả tổ tiên hoặc tự :: tất cả cùng nhau. Tôi nghĩ rằng yêu cầu không chỉ dành cho bất kỳ nút dữ liệu đầu tiên nào mà là một nút dữ liệu có id là 1. Câu hỏi không rõ ràng như nó có thể. – AnthonyWJones

11

Hãy chắc chắn rằng last() có phạm vi một cách chính xác. Hãy thử:

(/container/container/ancestor-or-self::container/data[@id="1"])[last()] 

Tương tự:

//container[last()] 

và:

(//container)[last()] 

không phải là những điều tương tự. Việc đầu tiên sẽ trả về nút chứa cuối cùng ở mỗi cấp của cấu trúc phân cấp - nhiều kết quả phù hợp - và nút thứ hai sẽ trả về nút vùng chứa cuối cùng được tìm thấy - một đối sánh.

+0

Aha, điều này đã làm việc! Cảm ơn bạn. –

+0

Thực ra, tôi phát hiện ra điều này không có tác dụng trong trường hợp nút con chứa được chỉ định trước phần tử dữ liệu phù hợp. –

+0

@Nick Spacek - Tôi đã cải thiện câu trả lời của mình bên dưới và giờ đây nó bao gồm cả trường hợp góc đó –

0

thử [position() = 1]

ví dụ:

/container/container/tổ tiên-or-self :: container/dữ liệu [vị trí() = 1]

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