XSLT2 context for for-each-group attributes

时间:2016-03-02 10:57:41

标签: xslt-2.0

I am fairly experienced with XSLT1, and have been starting to work with XSLT2. Most of the changes are easy enough to understand, but I am having a little trouble understanding how the attributes on a for-each-group element are evaluated in xslt2. Suppose that I have the following input document

<root>
    <item>1</item>
    <item>2</item>
    <item>3</item>
    <item>4</item>
    <item>5</item>
    <notanitem>abc</notanitem>
    <item>6</item>
    <item>7</item>
</root>

The following stylesheet

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0">
    <xsl:output method="xml" indent="yes"/>
    <xsl:template match="/">
        <result>
            <xsl:for-each-group select="root/item" group-by="(position() - 1) idiv 3">
                <row>
                    <xsl:for-each select="current-group()">
                        <cell><xsl:value-of select="."/></cell>
                    </xsl:for-each>
                </row>
            </xsl:for-each-group>
        </result>
    </xsl:template>
</xsl:stylesheet>

groups the items into rows with 3 cells each, producing

<result>
    <row>
        <cell>1</cell>
        <cell>2</cell>
        <cell>3</cell>
    </row>
    <row>
        <cell>4</cell>
        <cell>5</cell>
        <cell>6</cell>
    </row>
    <row>
        <cell>7</cell>
    </row>
</result>

Thus only the item elements are being counted in assigning positions.

Now, if I change the for-each-group to use group-starting-with="*[position() mod 3 = 1]". I get items 1, 2, and 3 in the first row; items 4 and 5 in the second row; and items 6 and 7 in the third row (so the notanitem element is being counted in assigning positions).

It seems that in the first case, the position function is evaluated only on the items, yet in the second case, the position function is evaluated on the entire document (or the children under the root element).

Is this the case? Is the group-by evaluation limited only to the items that actually are selected by the for-each-group construct, but the group-starting-with evaluation is based on the entire subtree that those elements are in (including unselected elements)? What is the context that those two attributes are evaluated in?

I feel that I almost have the right idea of how these work, but this is confusing me as I can't quite see the right way to interpret this in the specification, and other questions that I have looked at don't seem to be asking or answering about this.

1 个答案:

答案 0 :(得分:2)

group-by是计算分组键的表达式,group-starting-with是一种模式(您从XSLT 1.0知道match或{xsl:template属性1}})。

如果您使用xsl:key,则可以看到与group-starting-with="item[position() mod 3 = 1]"相同的结果。

至于group-by的评估,请参阅https://www.w3.org/TR/xslt20/#grouping,其中

  

在计算人口中项目的分组键时,   包含在group-by或group-adjacent属性中的表达式是   使用该项作为上下文项进行评估,其位置为   人口秩序作为上下文位置,并具有大小   人口作为背景大小。得到的序列是雾化的,   并且雾化序列中的每个原子值充当分组键   这个项目在人口中。

group-by https://www.w3.org/TR/xslt20/#dt-population被定义为population选择的序列:

  

[定义:要分组的项目序列,参考   作为总体,通过评估XPath表达式来确定   包含在select属性中。]

对于for-each-group select="expression"模式中的position()调用,首先需要查看模式,显然group-starting-with匹配所有元素,而不仅仅是*元素