【发布时间】:2018-03-29 10:59:17
【问题描述】:
我想使用 XSL 2.0 (saxon9he.jar) 按位置将数据分成组。 在此示例中,我尝试将市场产品拆分为袋子,每个袋子中包含 4 件商品。 我的测试表明 position() 在父级的范围内。这样马铃薯作为蔬菜部门的孩子是第 2 位,而不是我选择的产品中的第 5 位。 我想将组基于选择中的位置,而不是父级中的位置。
XML 数据集:
<market>
<department name="fruit">
<product>apple</product>
<product>banana</product>
<product>grape</product>
</department>
<department name="vegetable">
<product>carrot</product>
<product>potato</product>
<product>squash</product>
</department>
<department name="paper">
<product>plates</product>
<product>napkins</product>
<product>cups</product>
</department>
<department name="cloths">
<product>shirts</product>
<product>shorts</product>
<product>socks</product>
</department>
</market>
XSL 模板:
<xsl:transform version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2005/xpath-functions" exclude-result-prefixes="xs fn">
<xsl:output indent="no" method="text"/>
<!-- place 4 items in each bag -->
<xsl:template match="/">
<xsl:for-each-group select="/market/department/product"
group-ending-with="/market/department/product[position() mod 4 = 0]">
<xsl:variable name="file"
select="concat('bags/bag',position(),'.txt')"/>
<xsl:result-document href="{$file}">
<xsl:value-of select="position()"/>
<xsl:for-each select="current-group()">
<xsl:value-of select="."/>
</xsl:for-each>
</xsl:result-document>
</xsl:for-each-group>
</xsl:template>
</xsl:transform>
结果 bag1.txt
1applebananagrapecarrotpotatosquashplatesnapkinscupsshirtsshortssocks
结果 bag2.txt
file does not exist!
预期bag1.txt
1applebananagrapecarrot
预期bag2.txt
2potatosquashplatesnapkins
我的调试结论:
似乎 position() 永远不是 4 (每个部门只有 3 个项目)
如果我将 mod 4 更改为 mod 2 我会得到多个袋子,袋子 1 包含 2 件物品。但除最后一个之外的所有其他项目都包含 3 个项目。
每个袋子都在一个部门的第二个项目结束,除了第一个袋子之外,所有的袋子都包括前一个部门的最后一个项目。
结果 bag1.txt
1applebanana
结果 bag1.txt
2grapecarrotpotato
预期bag1.txt
1applebanana
预期bag2.txt
2grapecarrot
这向我表明 position() 与父项相关,而不是与选择相关。 我希望 position() 与选择相关。 根据我的研究, position() 应该与选择有关。 就像在这里的答案中描述的一样:
最后提示:position() 不会告诉你节点的位置 在其父级内。它告诉你当前节点的位置 相对于您现在正在处理的节点列表。
Find the position of an element within its parent with XSLT / XPath
这里提到,模式表达式与选择表达式相比,它们对范围的解释有所不同。看完后,不知道如何改变我对模式表达式的使用来实现我期望的行为。
Using for-each-group for high performance XSLT
根据我目前观察到的行为:
如果我有 9 个水果、4 个蔬菜和 20 个纸制品,并使用mod 5
bag1 将包含前 5 个水果产品,
bag2 将包含最后 4 个水果 + 4 个蔬菜 + 前 5 个纸制品。
当前行为不是我正在寻找的行为。
【问题讨论】: