xsl for-each-group 的迭代顺序是否一致?
Is order of iteration by xsl for-each-group consistent?
对于相同的数据,for-each-group 中的迭代顺序是否可以预测?或者如果同一个循环被执行两次它会改变吗,例如我在模板的不同部分重复了这个循环两次:
<xsl:for-each-group
select="descendant::FormSectionElements[not(LoadBindBase = '')]"
group-by="LoadBindBase">
... first ...
</xsl:for-each-group>
<xsl:for-each-group
select="descendant::FormSectionElements[not(LoadBindBase = '')]"
group-by="LoadBindBase">
... second ...
</xsl:for-each-group>
组之间的顺序在 XSLT 2.0 规范中定义,并且每次您使用相同的人口调用 xsl:for-each-group
指令时都是相同的(除非您使用 xsl:sort
).
分组操作的开销可能很大,建议您只执行一次。如有必要,您可以将分组的整个结果(或仅分组的某些特征,如 discussed in your previous question)放在一个变量中以供以后重用。
P.S。参见:http://xyproblem.info/
处理组的默认顺序是"order of first appearance":如果"London"作为分组键的第一次出现先于"Paris"的第一次出现,那么键为[=的组23=] 在键为 "Paris" 的组之前处理。您可以使用 xsl:sort 作为 xsl:for-each-group 的子项来更改顺序。在这两种情况下,顺序不仅在指令的多次使用之间是稳定的,而且在不同的实现之间是可预测和可互操作的。
我不确定我是否同意@michael.hor257k 将相同的分组进行两次是个坏主意。首先,在迁移到带有映射的 XSLT 3.0 之前,没有方便的数据结构来保存组。其次,这里有一个记忆时间权衡,所以这取决于你的情况。
在 3.0 中使用地图执行此操作的方法是:
<xsl:variable name="groups" as="map(xs:string, node()*)">
<xsl:map>
<xsl:for-each-group
select="descendant::FormSectionElements[not(LoadBindBase = '')]">
<xsl:map-entry key="current-grouping-key()" select="current-group()"/>
</xsl:for-each-group>
</xsl:map>
</xsl:variable>
然后您可以使用以下方法遍历组:
<xsl:for-each select="map:keys($groups)">
<group key="{.}">
<xsl:apply-templates select="$groups(.)" mode="xxx"/>
</group>
</xsl:for-each>
map:keys() 的处理顺序是不可预测的 -- 但它应该在多个调用中保持一致。
对于相同的数据,for-each-group 中的迭代顺序是否可以预测?或者如果同一个循环被执行两次它会改变吗,例如我在模板的不同部分重复了这个循环两次:
<xsl:for-each-group
select="descendant::FormSectionElements[not(LoadBindBase = '')]"
group-by="LoadBindBase">
... first ...
</xsl:for-each-group>
<xsl:for-each-group
select="descendant::FormSectionElements[not(LoadBindBase = '')]"
group-by="LoadBindBase">
... second ...
</xsl:for-each-group>
组之间的顺序在 XSLT 2.0 规范中定义,并且每次您使用相同的人口调用
xsl:for-each-group
指令时都是相同的(除非您使用xsl:sort
).分组操作的开销可能很大,建议您只执行一次。如有必要,您可以将分组的整个结果(或仅分组的某些特征,如 discussed in your previous question)放在一个变量中以供以后重用。
P.S。参见:http://xyproblem.info/
处理组的默认顺序是"order of first appearance":如果"London"作为分组键的第一次出现先于"Paris"的第一次出现,那么键为[=的组23=] 在键为 "Paris" 的组之前处理。您可以使用 xsl:sort 作为 xsl:for-each-group 的子项来更改顺序。在这两种情况下,顺序不仅在指令的多次使用之间是稳定的,而且在不同的实现之间是可预测和可互操作的。
我不确定我是否同意@michael.hor257k 将相同的分组进行两次是个坏主意。首先,在迁移到带有映射的 XSLT 3.0 之前,没有方便的数据结构来保存组。其次,这里有一个记忆时间权衡,所以这取决于你的情况。
在 3.0 中使用地图执行此操作的方法是:
<xsl:variable name="groups" as="map(xs:string, node()*)">
<xsl:map>
<xsl:for-each-group
select="descendant::FormSectionElements[not(LoadBindBase = '')]">
<xsl:map-entry key="current-grouping-key()" select="current-group()"/>
</xsl:for-each-group>
</xsl:map>
</xsl:variable>
然后您可以使用以下方法遍历组:
<xsl:for-each select="map:keys($groups)">
<group key="{.}">
<xsl:apply-templates select="$groups(.)" mode="xxx"/>
</group>
</xsl:for-each>
map:keys() 的处理顺序是不可预测的 -- 但它应该在多个调用中保持一致。