3

我正在阅读 XPath 的标准并试图了解它的一部分是如何工作的。

http://www.w3.org/TR/xpath/

xpath 标准似乎没有指出评估后代或自我的顺序(首先是上下文节点,或者首先是后代)。在 RFC 的一个阶段,它说它返回所有后代和上下文(如果存在)。在另一个阶段它说相反 - 它返回上下文节点和所有后代。

我的问题是:这个 XPath 的行为是什么:

/a//c

从逻辑的角度来看,这应该是进行深度优先搜索。因此,对于以下 XML:

<a>
  <b>
    <c v="1"/>
  </b>
  <c v="2"/>
</a>

这里的逻辑(以及似乎是实际的)行为似乎是结果将是:

c (v="1")
c (v="2")

但是,根据 RFC,//c 等效于:

/descendant-or-self::node()/child::c

这意味着,如果我做对了,那么行为可能会有所不同,具体取决于后代或自我的评估方式。

如果首先返回上下文节点,那么结果看起来应该是:

c(v="2")
c(v="1")

由于第一个节点在应用到时返回“//”a是 self(即a)。然后child::c被评估,我认为它会返回,因为那是c(v="2")它的第一个孩子......ac

有人可以指出解释为什么c(v="1")应该首先返回的 RFC 部分吗?

4

2 回答 2

4

从 XPath 1.0 规范:

轴是正向轴或反向轴。仅包含上下文节点或按文档顺序位于上下文节点之后的节点的轴是正向轴。仅包含上下文节点或按文档顺序位于上下文节点之前的节点的轴是反向轴。因此,祖先轴、祖先或自我轴、前轴和前兄弟轴是反向轴;所有其他轴都是正向轴。由于 self 轴始终最多包含一个节点,因此它是正向轴还是反向轴都没有区别。节点集的成员相对于轴的接近位置定义为节点集中的节点位置,如果轴是正向轴,则按文档顺序排序;如果轴是正向轴,则按反向文档顺序排序是反向轴。第一个位置是 1。

正如您在此处看到的,descendant-or-self是一个正向轴,因此相对于该轴的位置按文档顺序排列。

但是,我认为这几乎是您问题症结的一个有争议的问题。xsl:apply-templates使用,等时,节点集的内容始终按文档顺序处理xsl:for-each(见下文),因此 的内容/a//c将按文档顺序排列。

开启apply-templates(来自 XSLT 1.0 规范)

除非存在排序规范(参见 [10 Sorting]),否则将按文档顺序处理选定的节点集。

开启for-each(来自 XSLT 1.0 规范)

节点按文档顺序处理,除非存在排序规范(参见 [10 Sorting])。

更多关于轴的处理,来自(XPath 1.0 规范):

注意:谓词的含义主要取决于应用哪个轴。例如,previous::foo[1] 以相反的文档顺序返回第一个 foo 元素,因为应用于 [1] 谓词的轴是前面的轴;相比之下, (preceding::foo)[1] 返回文档顺序中的第一个 foo 元素,因为应用于 [1] 谓词的轴是子轴。

于 2013-03-04T08:02:12.233 回答
2

就 XPath 1.0 规范而言,XPath 表达式的结果是一个节点集,而不是一个序列,这意味着节点的顺序是未定义的。但是,XSLT 总是按文档顺序处理结果,因此,大多数其他 XPath API 也按文档顺序提供结果,尽管这不是正式要求。

一个完全独立的主语是谓词中“position()”的含义。松散地, position() 是指节点到上下文节点的距离,它与表达式结果返回的顺序无关。

于 2013-03-04T12:10:21.690 回答