Как я могу выбрать элемент с несколькими классами с помощью Xpath?
В приведенном выше примере xml я хотел бы выбрать все книги, принадлежащие классу foo, а не в строке класса, используя xpath.
<?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>
Ответы
Ответ 1
Добавив значение @class
в начало и конец пробела, вы можете проверить наличие "foo" и "bar", а не беспокоиться о том, было ли оно первым, средним или последним, и любые ложные положительные удары по "еда" или "бесплодные" значения @class
:
/bookstore/book[contains(concat(' ',@class,' '),' foo ')
and not(contains(concat(' ',@class,' '),' bar '))]
Ответ 2
Хотя мне нравится решение Mads: Вот еще один подход для XPath 2.0:
/bookstore/book[
tokenize(@class," ")="foo"
and not(tokenize(@class," ")="bar")
]
Обратите внимание, что следующие выражения являются истинными:
("foo","bar")="foo" -> true
("foo","bar")="bar" -> true
Ответ 3
XPath 2.0:
/*/*[for $s in concat(' ',@class,' ')
return
matches($s, ' foo ')
and
not(matches($s, ' bar '))
]
Здесь не выполняется токенизация, а $s вычисляется только один раз.
Или даже:
/*/book[@class
[every $t in tokenize(.,' ') satisfies $t ne 'bar']
[some $t in tokenize(.,' ') satisfies $t eq 'foo']
]