2010-04-20 10 views
9

Jak używać czegoś podobnego do poniższego przykładu, ale z przeciwnym rezultatem, tj. Elementów, które nie zawierają w tekście (default).Jak skonstruować ścieżkę x, aby wybrać elementy, które nie zawierają ciągów znaków?

<test> 
    <item>Some text (default)</item> 
    <item>Some more text</item> 
    <item>Even more text</item> 
</test> 

Biorąc pod uwagę to

//test/item[contains(text(), '(default)')] 

wróci pierwszy element. Czy istnieje operator, którego nie mogę użyć z plikami zawierającymi?

Odpowiedz

17

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.

Powiązane problemy