如何使用Xpath选择具有多个类的元素?

时间:2011-04-14 11:17:39

标签: xml xpath

在上面的xml示例中,我想通过使用xpath选择所有属于foo类的书而不是类吧。

<?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>

3 个答案:

答案 0 :(得分:36)

通过使用前导和尾随空格填充@class值,您可以测试“foo”和“bar”的存在,而不用担心它是第一个,中间还是最后一个,以及任何误报点击“食物”或“贫瘠”@class值:

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

答案 1 :(得分:11)

虽然我喜欢Mads解决方案:这是XPath 2.0的另一种方法:

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

请注意,以下表达式均为真:

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

答案 2 :(得分:4)

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']
       ]