XSL(T) 当前/上一个/下一个

Jam*_*mes 3 xslt

我知道 XSL 中有current()检索当前节点的功能,但是有没有办法能够引用当前位置的“上一个”和“下一个”节点?

Tom*_*lak 5

不。当前上下文无法知道哪些节点是“下一个”或“上一个”。

这是因为,例如,当应用模板时,其机制如下:

  1. 你做:<xsl:apply-templates select="*" /><!-- select 3 nodes (a,b,c) -->
  2. XSLT 处理器创建要处理的节点列表(a、b、c)
  3. 对于每个节点,XSLT 处理器选择并执行匹配的模板
  4. 当调用模板时,current()节点被定义,并且position()被定义,但除此之外,模板不知道执行流程。
  5. 执行顺序取决于处理器的偏好,只要保证结果相同即可。您的(理论)预测对于一个处理器可能是正确的,而对于另一个处理器则是错误的。对于像 XSLT 这样的无副作用编程语言,我认为这样的知识将是一件危险的事情(因为人们会开始依赖执行顺序)。

您可以使用following::siblingpreceding::siblingXPath 轴,但这与了解接下来要处理的节点不同

编辑

上面的解释试图回答所提出的问题,但OP的意思有所不同。它仅涉及分组/输出唯一节点。

根据 OP 的要求,这里快速演示了如何使用 XPath 轴实现分组。

XML(项目已预先排序):

<items>
  <item type="a"></item>
  <item type="a"></item>
  <item type="a"></item>
  <item type="a"></item>
  <item type="b"></item>
  <item type="e"></item>
</items>
Run Code Online (Sandbox Code Playgroud)

XSLT

<xsl:stylesheet 
  version="1.0" 
  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
>

  <xsl:template match="/items">
    <!-- copy the root element -->
    <xsl:copy>
      <!-- select those items that differ from any of their predecessors -->
      <xsl:apply-templates select="
        item[
          not(@type = preceding-sibling::item/@type)
        ]
      " />
    </xsl:copy>
  </xsl:template>

  <xsl:template match="item">
    <!-- copy the item to the output -->
    <xsl:copy-of select="." />
  </xsl:template>

</xsl:stylesheet>
Run Code Online (Sandbox Code Playgroud)

输出:

<items>
  <item type="a"></item>
  <item type="b"></item>
  <item type="e"></item>
</items>
Run Code Online (Sandbox Code Playgroud)