Re: [xsl] XSLT3 generic grouping functions

Subject: Re: [xsl] XSLT3 generic grouping functions
From: "Matthieu RICAUD-DUSSARGET m.ricaud-dussarget@xxxxxxxxxxxxxxxxxx" <xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx>
Date: Thu, 9 Jul 2020 10:23:08 -0000
Hi Martin,

Thanks you for theses feedbacks.

You are right, the function could be more generic with any sequence of nodes
as param. I'm use to always perform adjacent grouping within a XML document
tree in a specific context, in document order. But it's true there might be
other usecases.
I set a new issue here :
https://github.com/ELSGestion/els-sie-xsl-lib/issues/17

Yes <xsl:copy select="$wrapper"> is quite more readable instead of this dummy
loop to change the context. I commited this refacto.

Liebe Gr|_e

Matthieu

-----Message d'origine-----
De : Martin Honnen martin.honnen@xxxxxx
[mailto:xsl-list-service@xxxxxxxxxxxxxxxxxxxxxx]
Envoyi : mercredi 8 juillet 2020 11:36
@ : xsl-list@xxxxxxxxxxxxxxxxxxxxxx
Objet : Re: [xsl] XSLT3 generic grouping functions

Am 08.07.2020 um 11:24 schrieb Matthieu RICAUD-DUSSARGET
m.ricaud-dussarget@xxxxxxxxxxxxxxxxxx:
> Hi all,
>
> While teaching XSLT, someone ask if it was possible to have a kind of
> generic function to group XML elements.
>
> I first answer the only way to do it was to use (eventually nested)
> <xsl:for-each-group> instruction with specific conditions according to
> the data.
>
> Later, as I was discovering XSLT3, I realize the grouping condition
> might be sent as an higher-order-function parameter, which lead me to
> write some generic grouping functions to wrap XML elements (see
> example below).
>
> The original code can be found on github at
> https://github.com/ELSGestion/els-sie-xsl-lib/blob/master/src/main/xsl
> /els-common_xml.xsl
>
>
> There's also some generic xsl to nest titles
> (https://github.com/ELSGestion/els-sie-xsl-lib/blob/master/src/main/xs
> l/nest-titles.xsl) and a specific implementation of it to nest HTML
> titles
> (https://github.com/ELSGestion/els-sie-xsl-lib/blob/master/src/main/xs
> l/nest-html-titles.xsl)
>
> Working examples can be found in the test folder
> https://github.com/ELSGestion/els-sie-xsl-lib/tree/master/src/test, as
> xspec unit test or xspec driven integration tests.
>
> I actually have a bug with Saxon 9.9
> (https://saxonica.plan.io/issues/4636) on the generic starting-with
> grouping function, but this is an occasion to share theses grouping
> libraries J
>
> Any comments, feedbacks or similar code implementation are welcome !
>
> Cheers
>
> Matthieu Ricaud-Dussarget
>
> Example of generic adjacent grouping function used to define a
> specific "by-name grouping" implementation (there's a similar set of
> functions for starting-with) :
>
> <xd:doc>
>
>    <xd:desc>
>
>      <xd:p>Wrap adjacent elements into a new "wrapper" element</xd:p>
>
>      <xd:p>CAUTION : any text, pi, comments within context will be
> loose</xd:p>
>
>    </xd:desc>
>
>    <xd:param name="context">Parent of the adjacent elements to
> wrap</xd:param>
>
>    <xd:param name="adjacent.function">Xpath function to set the
> adjacency condition</xd:param>
>
>    <xd:param name="wrapper">Element wrapper</xd:param>
>
>    <xd:param name="keep-context">Say if the context should be kept or
> not in the result</xd:param>
>
>    <xd:return>context (or its content) with wrapped adjacent
> element</xd:return>
>
> </xd:doc>
>
> <xsl:function name="els:wrap-elements-adjacent" as="node()*">
>
>    <xsl:param name="context" as="element()"/>
>
>    <xsl:param name="adjacent.function"/> <!--as="xs:string"-->
>
>    <xsl:param name="wrapper" as="element()"/>
>
>    <xsl:param name="keep-context" as="xs:boolean"/>
>
>    <xsl:variable name="content" as="item()*">
>
>      <xsl:for-each-group select="$context/*"
> group-adjacent="$adjacent.function(.)">


I would certainly prefer to write a "generic" function that expects a
parameter with the grouping population as a sequence of nodes and then use

       <xsl:for-each-group select="$population" ...

I don't think for-each-group adjacent is meant to be used only for child
elements of a parent, if you want to use it in a generic way then provide a
population sequence you want to group.


>
>        <xsl:choose>
>
>          <xsl:when test="current-grouping-key()">
>
>            <xsl:for-each select="$wrapper">
>
>              <xsl:copy>
>
>                <xsl:copy-of select="@*"/>

Doesn't
              <xsl:copy select="$wrapper">

suffice in XSLT 3?

Why the xsl:for-each?

Current Thread