2012-09-02 11 views
6

Bir 'arama' düğümünden bilgi okuyabilen ve bunu kullanarak bir arama gerçekleştirebilen bir Xpath Bildirimi (1.0) yazmaya çalışıyorum.Arama parametresi boş veya eksik/yanlışsa, hiçbir şey döndürmek için Xpath işlevini ''() 'nasıl kullanabilirim?

Çok güzel bir ilerleme kaydediyordum, ancak bir özniteliğin (aramada bir değer için kullanılmış) boş veya mevcut olmaması durumunda sorun yaşadı.

Kod Düzenlendi basitleştirmek için Örnek: Yani burada

benim örnek XML geçerli:

<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> 

Ve çalışma XPATH:

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

Bu beklenen işleri olarak ...

Ancak beklenen özellik ise Eksik ya da boş çalışmaz. Çünkü bence: (@attrib, ""), bir sebepten ötürü her şeyle eşleşir, bu nedenle, öznitelik "" veya mevcut değilse, bir() ile hiçbir zaman uyuşmaz. Bunun için XML hariç parçasını değiştirmek eğer

Örnek için

, başarısız: Çok bununla

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

:

  <exclude></exclude> 

boş değeri için değil, kontrol için bir yol var mı Seçimi yap veya Mantığı yapılandırmanın belki daha iyi bir yolu var. Unutmayın ki Koşullu veya Xpath2.0'daki diğer işlevleri kullanamıyorum.

+0

Eğer, soruyu düzenlemek ve bir arama maçı bulmak için kuralları tarif edebilir misiniz - bunlar değil sağlanır ve uzun XPath ifadesini ziyade kafa karıştırıcı - Daha kısa bir ifadenin kullanılabileceğinden şüpheleniyorum. Örneğin: 'cond1 ve cond2 ya da cond1 ya da cond2', basit, eşdeğer ifade' cond1 ya da cond2' ile değiştirilebilir. –

+0

Bunun için üzgünüz. Kod örneklerini, sorunuma daha açık bir şekilde işaret etmek için güncelledim. – Futile32

+0

@ Futile32, belki de XPath'ınız düğümleri = "" ismine sahip olsun, ve hiç boş olmadığınız için hiç almıyorsunuz. –

cevap

0

gibi bir şey Yani bir de cevap rastladım söylemek istiyorum farklı gönderi. Aşağıda bunun bir örneği çalışıyor. Herkesin önerileri için teşekkürler.

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

Yerleştirdiğim yer "??" muhtemelen geçersiz bir char veya bir şeyle değiştirmek istiyordur. Kullanılan her ek karakter için 1+ artım gerektirir. Benim için dosya isimlerini kontrol ediyorum, bu yüzden bir soru işareti iyi bir fikir gibi görünüyor. Dürüst olmak gerekirse muhtemelen bu rotayı kullanmayacağım, tüm bu süreden sonra sorunu çözmeye hevesliydim.İşte

ben fikrim var nerede: How to give back constant if node does not exist in XPATH?

2

Xpath işlevi neden() param boş veya eksikse, her şeyi döndürür?

o XPath şartname contains() işlevi yapması gerektiğini söylediklerini Çünkü: $ arg2 değeri sıfır uzunluklu dize, döner doğrudur ardından fonksiyonudur

edin.

Sen XPath ayarlamak ve aşağıdaki koşullardan bazılarını basitleştirmek olabilir

:

//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

Referans için teşekkürler, ancak ben sorunu çözmek için farklı bir işlevi kullanabileceğim bir yol bulmayı umuyordum sanırım. Bunu belirtmek için sorumu geri aldım. – Futile32

0

Belki

//files/file[ 
    not(contains(@name, 
       //search[@id='1'] 
       /exclude/file/@term)) 
    or not(
    normalize-string(//search[@id='1'] 
         /exclude/file/@term) 
    ) 
] 
İlgili konular