具有多个谓词等价的xpath

时间:2015-02-06 05:38:49

标签: xpath xpath-2.0

有人告诉我,以下内容不一样:

a[1][@attr="foo"]
a[@attr="foo"][1]

有人可以解释为什么会这样吗?

1 个答案:

答案 0 :(得分:2)

将XPath表达式视为定义结果集 1 - 一组满足XPath表达式中所述要求的节点。 XPath表达式的谓词([]内部的部分)对结果集没有影响,或者它们逐渐缩小

换句话说,在下面的表达式中:

//xyz[@abc="yes"]

[@abc="yes"] 通过//xyz减少在其左侧定义的结果集。

请注意,正如Michael Kay所建议的那样,以下所述内容仅适用于具有至少一个位置谓词的XPath表达式。位置谓词可以是数字:[1]或评估为数字,或包含position()last()

如果不存在位置谓词,则XPath表达式中谓词的顺序不重要。


考虑以下简单的输入文档:

<root>
  <a attr="other"/>
  <a attr="foo"/>
  <a attr="other"/>
  <a attr="foo"/>
</root>

正如您所看到的,a[@attr = 'foo'] 不是 root的第一个子元素。如果我们申请

//a[1]

到本文档,这当然会导致

<a attr="other"/>

现在,至关重要的是,如果我们在表达式中添加另一个谓词,就像这样:

//a[1][@attr="foo"]

然后,[@attr="foo"]只能影响//a[1]定义的结果集。在此结果集中,没有a[@attr="foo"] - 最终结果为空。

另一方面,如果我们从

开始
//a[@attr="foo"]

结果将是

<a attr="foo"/>
-----------------------
<a attr="foo"/>

在这种情况下,如果我们添加第二个谓词:

//a[@attr="foo"][1]

第二个谓词[1]可以将//a[@attr="foo"]的结果集缩小到仅包含这些节点的第一个


如果您了解XSLT,您可能会发现XSLT(和XPath 2.0)证明这一点很有用:

<?xml version="1.0" encoding="UTF-8" ?>
<xsl:transform xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="yes" />

    <xsl:template match="/">
      <result1>
          <xsl:copy-of select="//a[1][@attr='foo']"/>
      </result1>
      <result2>
          <xsl:copy-of select="//a[@attr='foo'][1]"/>
      </result2>
    </xsl:template>

</xsl:transform>

结果将是

<result1/>
<result2>
   <a attr="foo"/>
</result2>

从技术上讲,只有XPath 1.0将此结果称为 node-set 。在XPath 2.0中,所有集合都已成为节点的真实序列