2011-01-13 11 views
6

Mam następujący węzeł XSLT:Jak mogę dodać wiele filtrów do instrukcji XSLT dla każdej?

<xsl:for-each select="Book[title != 'Moby Dick']"> 
.... 
</xsl:for-each> 

Jednak chciałbym użyć wielu filtrów w for-each. Próbowałem wykonać następujące czynności, ale to nie działa:

<!-- Attempt #1 --> 
<xsl:for-each select="Book[title != 'Moby Dick'] or Book[author != 'Rowling'] "> 
.... 
</xsl:for-each> 


<!-- Attempt #2 --> 
<xsl:for-each select="Book[title != 'Moby Dick' or author != 'Rowling']"> 
.... 
</xsl:for-each> 
+0

należy podać próbkę XML. – Flack

+0

Dobre pytanie, +1. Zobacz moją odpowiedź na wyjaśnienia i kilka rozwiązań jednoosobowych. :) –

Odpowiedz

19

Jednak chciałbym użyć wielu filtrów w for-each

Twoje prawdziwe pytanie jest XPath jeden: Czy to możliwe, i jak, aby określić więcej niż jeden warunek wewnątrz predykatu?

Odpowiedź:

Tak, używać standardowych operatorów logicznych or XPath i and i średnia funkcja XPath not().

W tym konkretnym przypadku, XPath w atrybucie select może być:

Book[title != 'Moby Dick' or author != 'Rowling'] 

Osobiście zawsze wolą pisać równoważne wyrażenie:

Book[not(title = 'Moby Dick') or not(author = 'Rowling')] 

ponieważ operator != ma nieintuicyjne zachowanie, gdy jeden z jego argumentów jest zbiorem węzłów.

Ale zgaduję, że to, czego prawdopodobnie chciał było and dwa comparissons - ich nieor.

+0

+1 Pełna i doskonała odpowiedź. –

+0

Jeśli masz szansę, czy mógłbybyś wyjaśnić lub połączyć się z wyjaśnieniem nieintuicyjnego zachowania operatora! Dzięki! –

+0

@Neil Whitaker: jeśli co najmniej jeden z operandów operatora '! =' Jest zbiorem węzłów (lub zbiorem węzłów lub sekwencją w XPath 2.0), możliwe jest, że zarówno '$ arg1 = $ arg2 'i' $ arg1! = $ arg2' są prawdziwe w tym samym czasie. Po prostu przeczytaj definicję operatora '! ='. Unika się tego, jeśli użyjesz 'not ($ arg1 = $ arg2)' –

0

Najwyraźniej zapomniałem odświeżyć moje dane. Próba nr 2 działa doskonale. Mam nadzieję, że ten przykład pomoże komuś innemu.

<!-- Attempt #2 --> 
<xsl:for-each select="Book[title != 'Moby Dick' or author != 'Rowling']"> 
.... 
</xsl:for-each> 
+0

@Dimitre - gdyby Rowling napisała książkę o nazwie Moby Dick, predykat z pewnością byłby fałszywy dla tej książki? –

+0

@Michael: Oczywiście, że masz rację. Prawdopodobnie sądziłem, że ten sam * element uczestniczył w dwóch porównaniach "! =" Z różnymi wartościami, które to porównania zostały następnie wyedukowane. Wczoraj musiałem być dość zmęczony ... W każdym razie usunąłem podobne stwierdzenie z mojej odpowiedzi. Dziękuję Ci. –

1

Jeśli potrzebujesz wielu predykatów, najprostszym sposobem jest użycie wielu predykatów. Zgaduję naprawdę chcesz „i” raczej niż „lub”:

<xsl:for-each select="Book[title != 'Moby Dick'][author != 'Rowling'] "> 
.... 
</xsl:for-each> 

Ogólnie = operator najlepiej unikać, ponieważ ma nieoczekiwane efekty, gdy autor jest nieobecny lub gdy istnieje wiele autorzy . Lepiej napisać:

<xsl:for-each select="Book[not(title = 'Moby Dick')][not(author = 'Rowling')] "> 
.... 
</xsl:for-each> 
Powiązane problemy