2015-02-06 82 views
2

有人告诉我,以下是不一样的:的XPath多谓词等价

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

有人能解释为什么会是这样?

回答

2

思考XPath表达式作为限定结果集 - 一组履行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"]的结果集为仅包含t他第一个那些节点。


如果你知道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将此结果称为节点集。在XPath 2.0中,所有集合都成为节点的真实序列

+0

嗡嗡声。感谢您通知我。我从来没有想过你解释的方式。 – 2015-02-06 10:13:41

+0

只要添加一个注释,谓词的顺序只有在至少其中一个是“位置”时才有意义。谓词是位置的,如果它评估为一个数字,或者它包含函数position()或last()上的调用。 – 2015-02-06 10:27:58

+0

@MichaelKay你是对的,这是一个重要的说明,我应该提到这一点!我马上编辑我的答案。 – 2015-02-06 10:30:10