2010-08-16 23 views
6

Tôi có tài liệu XML như:xpath 'hoặc' hành xử như công đoàn ('|') với xmllib2

<rootelement> 
<myelement>test1</myelement> 
<myelement>test2</myelement> 
<myelement type='specific'>test3</myelement> 
</rootelement> 

Tôi muốn lấy cụ thể myelementnếu nó không có mặt, sau đó mục đầu tiên. Vì vậy, tôi viết:

/rootelement/myelement[@type='specific' or position()=1] 

Các XPath spec bang về 'hoặc biểu hiện' rằng:

Các toán hạng phải là không được đánh giá nếu các toán hạng bên trái để đánh giá đúng

Vấn đề là libxml2-2.6.26 dường như áp dụng sự kết hợp của cả hai biểu thức, trả về một "2 Node Set" (ví dụ sử dụng xmllint --shell).

Có phải libxml2 hoặc tôi đang làm gì sai?

+0

Tốt câu hỏi (1). Xem câu trả lời của tôi cho một biểu thức XPath đơn mà chọn chính xác (các) nút mà bạn muốn. :) –

Trả lời

10

Câu trả lời ngắn: công cụ chọn của bạn không thể hiện suy nghĩ của bạn.


Các or hành công đoàn.

Phần thông số bạn đã trích dẫn ("Toán hạng bên phải không được đánh giá ...") là một phần của tiêu chuẩn boolean logic short circuiting. Đây là lý do tại sao bạn nhận được bộ nút 2 cho đầu vào ví dụ của bạn: XPath xem mỗi myelement là con của rootelement và áp dụng phần [@type='specific' or position()=1] cho mỗi nút như vậy để xác định xem nó có khớp với bộ chọn hay không.

  1. <myelement>test1</myelement> không khớp với @type='specific', nhưng không khớp với position()=1, vì vậy nó khớp với toàn bộ bộ chọn.
  2. <myelement>test2</myelement> không khớp với @type='specific' và cũng không khớp với position()=1, vì vậy, nó không khớp với toàn bộ công cụ chọn.
  3. <myelement type='specific'>test3</myelement> khớp với @type='specific' (vì vậy XPath không phải kiểm tra vị trí của nó - đó là phần ngắn mạch) sao cho nó khớp với toàn bộ bộ chọn.

Đầu tiên và cuối cùng <myelement> s khớp với toàn bộ bộ chọn để nó trả về bộ 2 nút.

Cách dễ nhất để chọn các yếu tố theo cách bạn muốn thực hiện theo hai bước.Đây là giả (Tôi không biết những gì bối cảnh mà bạn đang thực sự sử dụng XPath trong, và tôi không phải là quen thuộc với selectors viết XPath-cú pháp):

  1. Chọn elements phù hợp /rootelement/myelement[@type='specific']
  2. Nếu elements trống, chọn elements khớp với /rootelement/myelement[position()=1]
+0

sẽ ăn bạn: 1 cho lời giải thích rất tốt! –

7

@Matt Ball giải thích rất rõ nguyên nhân của sự cố.

Dưới đây là một XPath lót một lựa chọn chính xác những gì bạn muốn:

/*/myelement[@type='specific'] | /*[not(myelement[@type='specific'])]/myelement[1] 
+0

Dimitre, có vẻ như đã bị thiếu ')' trong biểu thức của bạn. Biểu thức của bạn chọn chính xác cùng một nút như của tôi, cụ thể là test1 và test3, đó không phải là ý định của tôi. BTW, tôi cũng đã thử (/ rootelement/myelement [@ type = 'specific' hoặc position() = 1]) [1], mang lại cho tôi test1 ... không tốt hơn. – foudfou

+0

@foudfou: cảm ơn vì đã chú ý đến điều này. Tôi đã sửa nó ngay bây giờ, vì vậy hãy thử lại một lần nữa. :) –

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