在嵌套上下文中使用 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() <= $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 <= position() and position() <= $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()
扩展功能。这可以缩短此处的代码。
使用 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() <= $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 <= position() and position() <= $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()
扩展功能。这可以缩短此处的代码。