Tak, jest:
//test/item[not(contains(text(), '(default)'))]
Podpowiedź: not()
jest funkcją w XPath zamiast operatora.
Alternatywą, ewentualnie lepszy sposób wyrazić to:
//test/item[not(text()[contains(., '(default)')])]
Istnieje subtelna, ale istotna różnica pomiędzy tymi dwoma wyrażeniami (nazwijmy je A i B, odpowiednio).
Prosta sprawa: Jeśli wszystko <item>
mieć tylko jeden węzeł tekst dziecko, zarówno A i B zachowują się tak samo.
Complex przypadek: Jeśli <item>
może mieć wielu węzeł tekstowy dzieci, wyrażenie A dopasowany tylko wtedy, gdy '(default)'
występuje w pierwszym z nich.
Dzieje się tak, ponieważ text()
dopasowuje wszystkie dzieci węzłów tekstu i tworzy zestaw węzłów. Jak dotąd nie jest zaskoczeniem. Teraz akceptuje zestaw węzłów jako swój pierwszy argument, ale musi przekonwertować go na ciąg znaków, aby wykonać to zadanie. A konwersja z zestawu węzłów na ciąg powoduje tylko wartość ciągu pierwszego węzła w zestawie, wszystkie inne węzły są pomijane (spróbuj string(//item)
, aby zobaczyć co mam na myśli). W tym prostym przypadku dokładnie to się dzieje, ale wynik nie jest tak zaskakujący.
Wyrażenie B radzi sobie z tym poprzez bezpośrednie sprawdzanie każdego węzła tekstowego indywidualnie, a nie tylko sprawdzanie wartości ciągu całego elementu <item>
. Dlatego jest bardziej wytrzymały z tych dwóch.