2012-09-02 20 views
6

Tôi đang cố gắng viết một Tuyên bố Xpath (1.0) có thể đọc thông tin từ nút 'tìm kiếm' và thực hiện tìm kiếm bằng cách sử dụng nó.Làm cách nào tôi có thể sử dụng hàm Xpath 'contains()' để trả về không có gì nếu tham số tìm kiếm của nó trống hoặc thiếu/sai?

Tôi đã thực hiện một số tiến bộ tốt đẹp, nhưng tình cờ gặp một vấn đề nếu một thuộc tính (được sử dụng cho một giá trị trong tìm kiếm) trống hoặc không tồn tại, nó không thành công.

Mã Edited để đơn giản hóa Ví dụ:

Vì vậy, đây là XML mẫu của tôi:

<xml> 
    <files> 
     <file name="foo" description="" rating="4"/> 
     <file name="food" description="" rating="4"/> 
     <file name="foobar" description="" rating="3"/> 
     <file name="bar" description="" rating="3"/> 
     <file name="barter" description="" rating="3"/> 
     <file name="barterer" description="" rating="2"/> 
    </files> 
    <searches> 
     <search id="1"> 
      <exclude> 
       <file term="foo"/> 
      </exclude> 
     </search> 
    </searches> 
</xml> 

Và XPATH làm việc:

//files/file[ 
      not(contains(@name, //search[@id='1']/exclude/file/@term)) 
] 

Nó hoạt động như mong đợi ...

Tuy nhiên, nếu thuộc tính mong đợi tôi s thiếu hoặc trống nó sẽ không hoạt động. Tôi nghĩ bởi vì: chứa (@attrib, "") phù hợp với mọi thứ vì lý do nào đó, do đó, không phải() sẽ luôn khớp với không có gì nếu thuộc tính là "" hoặc không có.

Ví dụ, nếu tôi thay đổi đoạn loại trừ của XML này nó không thành công:

  <exclude> 
       <file term=""/> 
      </exclude> 

với điều này quá:

  <exclude></exclude> 

Có cách nào để kiểm tra cho một giá trị rỗng và không thực hiện lựa chọn? hoặc có lẽ là một cách tốt hơn để cấu trúc Logic. Bare in mind Tôi không thể sử dụng Conditionals hoặc các chức năng khác trong Xpath2.0.

+0

thể bạn, xin vui lòng, chỉnh sửa câu hỏi và mô tả các quy tắc cho việc tìm kiếm một trận đấu tìm kiếm - đây không được cung cấp và biểu thức XPath dài là khá khó hiểu - Tôi nghi ngờ rằng một biểu thức ngắn hơn có thể được sử dụng. Ví dụ: 'cond1 và cond2 hoặc cond1 hoặc cond2' có thể được thay thế bằng biểu thức ngắn hơn, tương đương' cond1 hoặc cond2'. –

+0

Xin lỗi về điều đó. Tôi đã cập nhật các ví dụ về Mã để rõ ràng hơn cho vấn đề của tôi. – Futile32

+0

@ Futile32, có thể XPath của bạn nhận được các nút có tên = "" và bởi vì bạn không có nút nào, bạn không nhận được bất kỳ thẻ nào. –

Trả lời

0

Vì vậy, tôi tình cờ câu trả lời trong một bài đăng khác nhau. Dưới đây là một ví dụ về nó hoạt động. Cảm ơn lời khuyên của mọi người.

//files/file[ 
    not(
     contains(
      @name, 
      concat(//search[@id='1']/exclude/file/@term, 
       substring('??', 1 + 2* 
        boolean(substring(//search[@id='1']/exclude/file/@term, 1)) 
       ) 
      ) 
     ) 
    ) 
] 

bit mà tôi đặt "??" có lẽ muốn thay thế bằng một char không hợp lệ hoặc một cái gì đó. Đối với mỗi ký tự bổ sung sử dụng 1+ cần tăng. Đối với tôi, tôi đang kiểm tra tên tập tin để một dấu chấm hỏi có vẻ là một ý tưởng hay. Thành thật mà nói, tôi có lẽ sẽ không sử dụng tuyến đường này, tôi chỉ mong muốn giải quyết vấn đề sau tất cả thời gian này.

Đây là nơi tôi đã có ý tưởng từ: How to give back constant if node does not exist in XPATH?

2

Tại sao hàm Xpath chứa() trả về mọi thứ nếu nó tìm kiếm thông số trống hoặc bị thiếu?

Bởi vì đó là những gì đặc tả XPath nói contains() chức năng nên làm:

Nếu giá trị của $ arg2 là chuỗi số không dài, sau đó chức năng trả về true.

Bạn có thể điều chỉnh XPath của bạn và đơn giản hóa một số điều kiện như sau:

//files/file[ 
      ( 
       (
        not(//search[@id='1']/include/file/@term) 
        or 
        (
        contains(@name, //search[@id='1']/include/file/@term) 
        or 
        contains(@description, //search[@id='1']/include/file/@term) 
        ) 
       ) 
       or 
       contains(@rating, //search[@id='1']/include/file/@rating) 
      )  
      and 
      ( 
       (
        not(//search[@id='1']/exclude/file/@term) 
        or 
        (
        not(contains(@name, //search[@id='1']/exclude/file/@term)) 
        and 
        not(contains(@description, //search[@id='1']/exclude/file/@term)) 
        ) 
       ) 
       and 
       (
        not(//search[@id='1']/exclude/file/@rating) 
        or 
        not(contains(@rating, //search[@id='1']/exclude/file/@rating)) 
       ) 
      ) 

      ] 
+0

Cảm ơn bạn đã tham khảo, tuy nhiên tôi đoán tôi đã hy vọng tìm được cách tôi có thể sử dụng chức năng khác để giải quyết vấn đề của mình. Tôi đã viết lại câu hỏi của mình để chỉ ra điều đó. – Futile32

0

Có lẽ bạn muốn nói điều gì đó như

//files/file[ 
    not(contains(@name, 
       //search[@id='1'] 
       /exclude/file/@term)) 
    or not(
    normalize-string(//search[@id='1'] 
         /exclude/file/@term) 
    ) 
] 
Các vấn đề liên quan