Re: [xsl] XPath expression that yields the same result as xsl:for-each-group?

Subject: Re: [xsl] XPath expression that yields the same result as xsl:for-each-group?
From: "Michael Kay mike@xxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 30 May 2019 14:10:08 -0000
I would normally use maps for grouping in XPath 3.1. Ignoring the problem of
composite keys

map:merge(//row ! map:entry( key, .),
                   map{"duplicates":"combine"})

If the grouping key is composite, as in this example, then you can either form
a key by string concatenation, or use a multi-level map.

Michael Kay
Saxonica


> On 30 May 2019, at 14:06, Martin Honnen martin.honnen@xxxxxx
<xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx> wrote:
>
> On 30.05.2019 14:46, Costello, Roger L. costello@xxxxxxxxx wrote:
>> Hello XSLT/XPath experts!
>>
>> My XML document consists of a series of rows.
>>
>> Each row is identified by the combination of two child elements:
ARPT__IDENT and TRM__IDENT.
>>
>> I want to group the rows. A group consists of those rows with the same
ARPT__IDENT and TRM__IDENT.
>>
>> This XML document:
>>
>> <Test>
>>     <row>
>>         <ARPT__IDENT>A</ARPT__IDENT>
>>         <TRM__IDENT>X</TRM__IDENT>
>>         <Data>Foo</Data>
>>     </row>
>>     <row>
>>         <ARPT__IDENT>A</ARPT__IDENT>
>>         <TRM__IDENT>X</TRM__IDENT>
>>         <Data>Bar</Data>
>>     </row>
>>     <row>
>>         <ARPT__IDENT>A</ARPT__IDENT>
>>         <TRM__IDENT>Y</TRM__IDENT>
>>         <Data>Blah</Data>
>>     </row>
>>     <row>
>>         <ARPT__IDENT>A</ARPT__IDENT>
>>         <TRM__IDENT>Y</TRM__IDENT>
>>         <Data>Plugh</Data>
>>     </row>
>> </Test>
>>
>> is to be grouped this way:
>>
>> <results>
>>     <group>
>>         <row>
>>             <ARPT__IDENT>A</ARPT__IDENT>
>>             <TRM__IDENT>X</TRM__IDENT>
>>             <Data>Foo</Data>
>>         </row>
>>         <row>
>>             <ARPT__IDENT>A</ARPT__IDENT>
>>             <TRM__IDENT>X</TRM__IDENT>
>>             <Data>Bar</Data>
>>         </row>
>>     </group>
>>     <group>
>>         <row>
>>             <ARPT__IDENT>A</ARPT__IDENT>
>>             <TRM__IDENT>Y</TRM__IDENT>
>>             <Data>Blah</Data>
>>         </row>
>>         <row>
>>             <ARPT__IDENT>A</ARPT__IDENT>
>>             <TRM__IDENT>Y</TRM__IDENT>
>>             <Data>Plugh</Data>
>>         </row>
>>     </group>
>> </results>
>>
>> I can use xsl:for-each-group to perform the grouping:
>>
>> <xsl:template match="Test">
>>     <xsl:variable name="rows" select="row" as="element(row)*"/>
>>     <results>
>>         <xsl:for-each-group select="$rows" group-by="concat(ARPT__IDENT,
'|', TRM__IDENT)">
>>             <group>
>>                 <xsl:sequence select="current-group()" />
>>             </group>
>>         </xsl:for-each-group>
>>     </results>
>> </xsl:template>
>>
>> However, I want to create a variable -- $groups -- which holds the groups
and then iterate over the variable:
>>
>> <results>
>>     <xsl:for-each select="$groups">
>>         <group>
>>             <xsl:sequence select="." />
>>         </group>
>>     </xsl:for-each>
>> </results>
>>
>> What XPath expression will yield the desired value for $groups?
>>
>> <xsl:variable name="groups" select="???" />
>>
>> Is there an XPath 2.0 expression that can be used?
>
> What kind of sequence type would you expect that XPath expression to
> return? You can't build sequences of sequences to somehow wrap the items
> belonging to a group.
>
> So unless you could move to XPath 3.1 with maps and/or arrays I don't
> see an XPath type constructed with pure XPath to hold groups. And of
> course even there it would be easier and smarter to use XSLT to create
> the map or the nested sequence/array or array/sequence structure than to
> rely on pure XPath I think.

Current Thread