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>
  1. 组之间的顺序在 XSLT 2.0 规范中定义,并且每次您使用相同的人口调用 xsl:for-each-group 指令时都是相同的(除非您使用 xsl:sort).

  2. 分组操作的开销可能很大,建议您只执行一次。如有必要,您可以将分组的整个结果(或仅分组的某些特征,如 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() 的处理顺序是不可预测的 -- 但它应该在多个调用中保持一致。