[Bug 5166] [XSLT 2++] Enhancement: sorting and grouping

http://www.w3.org/Bugs/Public/show_bug.cgi?id=5166

           Summary: [XSLT 2++] Enhancement: sorting and grouping
           Product: XPath / XQuery / XSLT
           Version: Recommendation
          Platform: PC
        OS/Version: Windows XP
            Status: NEW
          Severity: enhancement
          Priority: P2
         Component: XSLT 2.0
        AssignedTo: mike@saxonica.com
        ReportedBy: mike@saxonica.com
         QAContact: public-qt-comments@w3.org


Discussions on grouping in XQuery today, and solving some tricky positional
grouping problems for a client over the last week, prompt me to capture
extensions that could be made to XSLT grouping and sorting capabilities:

(a) allow xsl:variable before xsl:sort, to compute a value that can be used
both in the sort key expression and in the subsequent processing of the
relevant item:

<xsl:for-each select="product">
  <xsl:variable name="profitability" select="price - cost"/>
  <xsl:sort select="$profitability"/>
  <xsl:value-of select="$profitability"/>
</xsl:for-each>

(b) allow grouping keys to be specified in a separate group element:

<xsl:for-each-group select="product">
  <xsl:group-by select="price"/>
  <xsl:value-of select="avg(current-group()/cost)"/>
</xsl:for-each-group>

(c) use this to allow composite grouping keys

<xsl:for-each-group select="product">
  <xsl:group-by select="category"/>
  <xsl:group-by select="colour"/>
  <xsl:value-of select="avg(current-group()/cost)"/>
</xsl:for-each-group>

(d) allow control over how a sequence-valued group key is handled

<xsl:group-by select="author" compare="each | first | only | sequence | set"/>

(each assigns to one group for each value of the key; first ignores all but the
first, only requires exactly one, sequence compares the sequences as sequences,
set compares them as sets)

(e) allow variables to be declared before the group-by:

<xsl:for-each-group select="product">
  <xsl:variable name="profitability" select="(price - cost) div cost"/>
  <xsl:variable name="profit-band" select="$profitability idiv 0.2"/>
  <xsl:group-by select="$profit-band"/>
  <xsl:value-of select="format-number($profit-band)"/>
</xsl:for-each-group>

or

<xsl:for-each-group select="*">
  <xsl:variable name="is-bullet" select="boolean(self::bullet)"/>
  <xsl:group-adjacent select="$is-bullet"/>
  <xsl:choose>
    <xsl:when test="$is-bullet">
       ...
</xsl:for-each-group>

(e) group-starting-when in place of group-starting-with; the value is an
expression rather than a pattern, and a new group starts when the expression is
true. Allows the same concepts as above to be used for this case (and
group-ending-when).

<xsl:for-each-group select="para">
  <xsl:variable name="is-top-level" select="@level = 0"/>
  <xsl:variable name="is-heading" select="title and not
preceding-sibling::*[1]/self::title"/>
  <xsl:group-starting-when test="$is-top-level and $is-heading"/>
  <xsl:if test="$is-heading">

Received on Tuesday, 9 October 2007 05:07:14 UTC