【问题标题】:How can I select an element with multiple classes with Xpath?如何使用 Xpath 选择具有多个类的元素?
【发布时间】:2011-08-05 11:11:08
【问题描述】:

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

<?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。请参阅我对两种不同 XPath 2.0 解决方案的回答,其中第一种可能是最有效的,尤其是使用非优化的 XPath 2.0 引擎时。

标签: xml xpath


【解决方案1】:

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

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

【讨论】:

  • 如果@class 包含制表符甚至换行符而不是空格怎么办。 normalize-space 函数 (XPath 1.0) 派上用场了,它从字符串中去除前导和尾随空白,用单个空格替换空白字符序列,例如concat(' ',normalize-space(@class),' ')
  • @Steven Pribilinskiy - 这应该没有必要。由于 XML 解析器如何规范化属性值,制表符和回车将已经规范化为空格。 w3.org/TR/xml/#AVNormalize
【解决方案2】:

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

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

请注意,以下表达式都是正确的:

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

【讨论】:

  • +1 表示 XPath 2.0 解决方案。有了 2.0,很多事情都变得简单了。
【解决方案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']
       ]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-14
    • 2011-11-30
    • 2017-11-22
    相关资源
    最近更新 更多