在嵌套上下文中使用 position() 的 XPath 不会产生所需的结果

XPath using position() in a nested context does not produce the desired result

使用 XPath 1,我正在尝试 return 某个范围内 item 的节点集,其中具有不同的 dept_number 值。这些项目所在的范围是动态的。该文档的结构如下:

<data>
    <items>
        <item>
            <dept_number>1</dept_number>
        </item>
        <item>
            <dept_number>1</dept_number>
        </item>
        <item>
            <dept_number>2</dept_number>
        </item>
        <item>
            <dept_number>2</dept_number>
        </item>
        <item>
            <dept_number>3</dept_number>
        </item>
        <item>
            <dept_number>4</dept_number>
        </item>
        <item>
            <dept_number>4</dept_number>
        </item>
    </items>
</data>

我能想到的最好的方法如下:

/data/items/item[not(dept_number = preceding-sibling::item[position() > $min]/dept_number) and position() > $min and position() <= $max]/dept_number

其中 $min 是范围的下限,$max 是上限。这是行不通的。例如,如果我使用

/data/items/*[name() = 'item' and not(dept_number = preceding-sibling::*[position() > 1]/dept_number) and position() > 1 and position() <= 5]/dept_number

它returns

<dept_number>1</dept_number>
<dept_number>2</dept_number>
<dept_number>2</dept_number>
<dept_number>3</dept_number>

这不是一组不同的值。我期望的是

<dept_number>1</dept_number>
<dept_number>2</dept_number>
<dept_number>3</dept_number>

我认为问题在于在嵌套上下文中使用 position()(即 /data/items/item[... preceding-sibling::item[position() > $min] ...])。它似乎使用了在外部使用时从 position() 获得的结果上下文,而不是内部上下文。

在 xslt 中,我也尝试过这样使用键:

<xsl:key name="dept_number_key" match="/data/items/item" use="dept_number"/>
<xsl:for-each select="/data/items/item[generate-id() = generate-id(key('dept_number_key', dept_number)[1]) and position() $gt; $min-pos and position() &lt;= $max-pos]">
</xsl:for-each>

但这仍然不起作用。

如有任何帮助,我们将不胜感激。

编辑:我指的范围不是 dept_number 值的范围,而是 <items> 内的 <item> 标签的范围。例如,如果范围是 3 到 5,我想取回 <items>.

中的第三个、第四个和第五个 <item> 标签

--- 根据澄清进行编辑 ---

我首先将范围内的项目复制到一个新的 "document",这样您以后就可以对它们使用 Muenchian 分组以仅获取不同的值。如果没有这个,分组可能会失败,例如,如果项目 #3 不是具有给定 dept_number 值的第一个项目。

考虑以下样式表:

XSLT 1.0 + EXSLT 节点集() 函数

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:exsl="http://exslt.org/common"
extension-element-prefixes="exsl">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>

<xsl:variable name="min-pos" select="3" />
<xsl:variable name="max-pos" select="5" />

<xsl:key name="dept_number_key" match="item" use="dept_number" />

<xsl:template match="/data">
    <xsl:variable name="items-in-range">
        <xsl:copy-of select="items/item[$min-pos &lt;= position() and position() &lt;= $max-pos]"/>
    </xsl:variable>
    <root>
        <xsl:copy-of select="exsl:node-set($items-in-range)/item[generate-id() = generate-id(key('dept_number_key', dept_number)[1])]/dept_number"/>
    </root>
</xsl:template>

</xsl:stylesheet>

请注意,某些 XSLT 1.0 处理器支持 EXSLT set:distinct() 扩展功能。这可以缩短此处的代码。