On 6/16/2023 1:09 PM, Matthieu Ricaud-Dussarget ricaudm@xxxxxxxxx wrote:
>
> Hi all,
>
> I need to group elements that have at least one common valueB :
>
> <FORMS>
>
> <!--CASE 1-->
>
> <GRCHOIX CODE="grchoix-1">
>
> <CHOIX CODE="choix-1"/>
>
> <CHOIX CODE="choix-2"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-2">
>
> <CHOIX CODE="choix-1"/>
>
> <CHOIX CODE="choix-2"/>
>
> <CHOIX CODE="choix-3"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-3">
>
> <CHOIX CODE="choix-2"/>
>
> <CHOIX CODE="choix-3"/>
>
> <CHOIX CODE="choix-4"/>
>
> </GRCHOIX>
>
> <!--CASE 2-->
>
> <GRCHOIX CODE="grchoix-A">
>
> <CHOIX CODE="choix-a"/>
>
> <CHOIX CODE="choix-b"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-B">
>
> <CHOIX CODE="choix-b"/>
>
> <CHOIX CODE="choix-c"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-C">
>
> <CHOIX CODE="choix-d"/>
>
> <CHOIX CODE="choix-e"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-D">
>
> <CHOIX CODE="choix-c"/>
>
> <CHOIX CODE="choix-d"/>
>
> </GRCHOIX>
>
> </FORMS>
>
> * grchoix-1 and grchoix-2 have 2 common valuesB : choix-1, choix-2 b
> they must belong the same group
>
> * grchoix-2 and grchoix-3 have 2 common valuesB : choix-2, choix-3 b
> they must belong the same group
>
> b At the end : grchoix-1, grchoix-2 and grchoix-3 must belong the same
> group
>
> * grchoix-A and grchoix-B have 1 common valueB choix-b b they must
> belong the same group
>
> * grchoix-B and grchoix-C have 0 common values
>
> * but as grchoix-D have
>
> - 1 common value (choix-c) with grchoix-B
>
> - 1 one common value (choix-d) with grchoix-C
>
> Then grchoix-B and grchoix-C must also belong the same GROUP
>
> b At the end : grchoix-A, grchoix-B, grchoix-C and grchoix-D must
> belong the same group
>
> The expected XML output is 2 Groups :
>
> <FORMS>
>
> <!--CASE 1-->
>
> <GROUP>
>
> <GRCHOIX CODE="grchoix-1">
>
> <CHOIX CODE="choix-1"/>
>
> <CHOIX CODE="choix-2"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-2">
>
> <CHOIX CODE="choix-1"/>
>
> <CHOIX CODE="choix-2"/>
>
> <CHOIX CODE="choix-3"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-3">
>
> <CHOIX CODE="choix-2"/>
>
> <CHOIX CODE="choix-3"/>
>
> <CHOIX CODE="choix-4"/>
>
> </GRCHOIX>
>
> </GROUP>
>
> <!--CASE 2-->
>
> <GROUP>
>
> <GRCHOIX CODE="grchoix-A">
>
> <CHOIX CODE="choix-a"/>
>
> <CHOIX CODE="choix-b"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-B">
>
> <CHOIX CODE="choix-b"/>
>
> <CHOIX CODE="choix-c"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-C">
>
> <CHOIX CODE="choix-d"/>
>
> <CHOIX CODE="choix-e"/>
>
> </GRCHOIX>
>
> <GRCHOIX CODE="grchoix-D">
>
> <CHOIX CODE="choix-c"/>
>
> <CHOIX CODE="choix-d"/>
>
> </GRCHOIX>
>
> </GROUP>
>
> </FORMS>
>
I think the following XSLT 3 produces the wanted result:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
B B B xmlns:xs="http://www.w3.org/2001/XMLSchema"
B B B exclude-result-prefixes="#all"
B B B version="3.0">
B <xsl:output method="xml" indent="yes"/>
B <xsl:template match="FORMS">
B B B <xsl:copy>
B B B B B <xsl:variable name="groups" as="map(xs:untypedAtomic,
element(GRCHOIX)*)*">
B B B B B B B <xsl:for-each-group select="GRCHOIX" group-by="CHOIX/@CODE">
B B B B B B B B B <xsl:map-entry key="current-grouping-key()"
select="current-group()"/>
B B B B B B B </xsl:for-each-group>
B B B B B </xsl:variable>
B B B B B <xsl:iterate select="$groups">
B B B B B B B <xsl:param name="group" select="()"/>
B B B B B B B <xsl:on-completion>
B B B B B B B B B <GROUP>
B B B B B B B B B B B <xsl:sequence select="$group?*/."/>
B B B B B B B B B </GROUP>
B B B B B B B </xsl:on-completion>
B B B B B B B <xsl:choose>
B B B B B B B B B <xsl:when test="empty($group) or $group?*/CHOIX/@CODE =
?*/CHOIX/@CODE">
B B B B B B B B B B B <xsl:next-iteration>
B B B B B B B B B B B B B <xsl:with-param name="group" select="$group, ."/>
B B B B B B B B B B B </xsl:next-iteration>
B B B B B B B B B </xsl:when>
B B B B B B B B B <xsl:otherwise>
B B B B B B B B B B B <GROUP>
B B B B B B B B B B B B B <xsl:sequence select="$group?*/."/>
B B B B B B B B B B B </GROUP>
B B B B B B B B B B B <xsl:next-iteration>
B B B B B B B B B B B B B <xsl:with-param name="group" select="()"/>
B B B B B B B B B B B </xsl:next-iteration>
B B B B B B B B B </xsl:otherwise>
B B B B B B B </xsl:choose>
B B B B B </xsl:iterate>
B B B </xsl:copy>
B </xsl:template>
</xsl:stylesheet>
|