2011-04-14 14 views
27

Yukarıdaki xml örneğinde, xpath kullanarak sınıf çubuğuna değil, sınıf çubuğuna ait olan tüm kitapları seçmek istiyorum. ön ve sonunda boşluk ile @class değeri doldurma ileXpath ile birden çok sınıf içeren bir öğeyi nasıl seçebilirim?

<?xml version="1.0" encoding="ISO-8859-1"?> 
<bookstore> 
    <book class="foo"> 
    <title lang="en">Harry Potter</title> 
    <author>J K. Rowling</author> 
    <year>2005</year> 
    <price>29.99</price> 
    </book> 
    <book class="foo bar"> 
    <title lang="en">Harry Potter</title> 
    <author>J K. Rowling</author> 
    <year>2005</year> 
    <price>29.99</price> 
    </book> 
    <book class="foo bar"> 
    <title lang="en">Harry Potter</title> 
    <author>J K. Rowling</author> 
    <year>2005</year> 
    <price>29.99</price> 
    </book> 
</bookstore> 
+2

İyi soru 1. En başta, optimize olmayan bir XPath 2.0 motoruyla, bunların en verimli olabileceği iki farklı XPath 2.0 çözümü için cevabımı görün. –

cevap

33

, Eğer "foo" ve "bar" mevcudiyeti için test etmek ve son, ilk orta ya da olmadığı konusunda endişe ve herhangi bir yanlış pozitif olabilir "gıda" veya "kısır" @class değerleri üzerinde hit:

/bookstore/book[contains(concat(' ',@class,' '),' foo ') 
     and not(contains(concat(' ',@class,' '),' bar '))] 
+1

Eğer '@ class' alan yerine sekme hatta yeni satır karakteri içeriyorsa ne olur? Burada, bir dizgeden öndeki ve sondaki beyaz boşluğu kesen normalize-uzay fonksiyonunun (XPath 1.0) kullanışlı olması, boşluk karakterlerinin sıralarının tek bir boşlukla, örneğin; concat ('', normalize alan (@class), '') ' –

+0

@Steven Pribilinskiy - Bu gerekli olmamalıdır. Öznitelik değerlerinin XML ayrıştırıcısı tarafından normalleştirilmesi nedeniyle, sekmeler ve satırbaşı dönüşleri zaten bir alana normalleştirilmiştir. http://www.w3.org/TR/xml/#AVNormalize –

+0

Bu daha iyi bir yanıttır: XPath 2.0 çözümü için http://stackoverflow.com/a/3881148/557406 –

11

Mads'in çözüm gibi olsa:

/bookstore/book[ 
       tokenize(@class," ")="foo" 
       and not(tokenize(@class," ")="bar") 
       ] 

o t unutmayın: İşte XPath 2.0 için başka bir yaklaşımdır O şu ifadeler ikisi de doğruysa:

("foo","bar")="foo" -> true 
("foo","bar")="bar" -> true 
+0

+1. 2.0 ile pek çok şey daha kolay. Tek hesaplama optimizasyonu için –

4

XPath 2.0: İşte

/*/*[for $s in concat(' ',@class,' ') 
      return 
       matches($s, ' foo ') 
      and 
       not(matches($s, ' bar ')) 
     ] 

hiçbir dizgeciklere yapılır ve $ s sadece bir kez hesaplanır.

Hatta:

/*/book[@class 
      [every $t in tokenize(.,' ') satisfies $t ne 'bar'] 
      [some $t in tokenize(.,' ') satisfies $t eq 'foo'] 
     ] 
+0

+1. – topless

+0

@ Chris-Top: Rica ederim. –

İlgili konular