'Group by key in xslt 3.0

I am trying to group by an attribute . Example input:

<?xml version='1.0' encoding='UTF-8'?>
<ns1:map xmlns:ns1="http://www.w3.org/2005/xpath-functions">
  <ns1:string key="omschrijving">Inschrijfstaat Raamovereenkomst</ns1:string>
  <ns1:map key="concepten">
    <ns1:map key="http://url/def/Document">
      <ns1:string key="iri">http://url/def/Document</ns1:string>
      <ns1:string key="naam">Create Document</ns1:string>
    </ns1:map>
  </ns1:map>
  <ns1:map key="collecties">
    <ns1:map key="4a9ff131-a507-4979-817a-09ae4365386a">
      <ns1:string key="uuid">4a9ff131-a507-4979-817a-09ae4365386a</ns1:string>
      <ns1:string key="naam">meeden</ns1:string>
    </ns1:map>
  </ns1:map>
  <ns1:map key="eigenschapConcepten">
    <ns1:map key="http://url/def/4c20ec8e-8e86-30ca-89a0-96e8ecad447d">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">tekst</ns1:string>
          <ns1:string key="waarde">112</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="http://url/def/7d94197f-78b5-3f8f-9068-a99235fda655">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">tekst</ns1:string>
          <ns1:string key="waarde">nld</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="http://url/def/2c0bea42-27b1-35aa-aa93-c91d22a2a78e">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">tekst</ns1:string>
          <ns1:string key="waarde">Inschrijfstaat Raamovereenkomst</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="https://url/43514c35-3699-4cf2-abaa-ac2906c41e7f">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">tekst</ns1:string>
          <ns1:string key="waarde">G014485-BEG-2139</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="http://url/def/hasVersion">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">entiteit</ns1:string>
          <ns1:string key="entiteitUuid">cb020428-ec25-44f7-8add-7e334eb2a3c0</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="https://w3id.org/def/basicsemantics-owl#describes">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">entiteit</ns1:string>
          <ns1:string key="entiteitUuid">004ed20d-1292-4210-a541-755754497fbe</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="https://w3id.org/def/basicsemantics-owl#describes">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">entiteit</ns1:string>
          <ns1:string key="entiteitUuid">004ed20d-1292-4210-a541-755754497fba</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
  </ns1:map>
</ns1:map>

Expected output:

<?xml version='1.0' encoding='UTF-8'?>
<ns1:map xmlns:ns1="http://www.w3.org/2005/xpath-functions">
  <ns1:string key="omschrijving">Inschrijfstaat Raamovereenkomst</ns1:string>
  <ns1:map key="concepten">
    <ns1:map key="http://url/def/Document">
      <ns1:string key="iri">http://data.tennet.eu/def/Document</ns1:string>
      <ns1:string key="naam">Create Document</ns1:string>
    </ns1:map>
  </ns1:map>
  <ns1:map key="collecties">
    <ns1:map key="4a9ff131-a507-4979-817a-09ae4365386a">
      <ns1:string key="uuid">4a9ff131-a507-4979-817a-09ae4365386a</ns1:string>
      <ns1:string key="naam">meeden</ns1:string>
    </ns1:map>
  </ns1:map>
  <ns1:map key="eigenschapConcepten">
    <ns1:map key="http://url/def/4c20ec8e-8e86-30ca-89a0-96e8ecad447d">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">tekst</ns1:string>
          <ns1:string key="waarde">112</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="http://url/def/7d94197f-78b5-3f8f-9068-a99235fda655">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">tekst</ns1:string>
          <ns1:string key="waarde">nld</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="http://url/def/2c0bea42-27b1-35aa-aa93-c91d22a2a78e">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">tekst</ns1:string>
          <ns1:string key="waarde">Inschrijfstaat Raamovereenkomst</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="https://url/43514c35-3699-4cf2-abaa-ac2906c41e7f">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">tekst</ns1:string>
          <ns1:string key="waarde">G014485-BEG-2139</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="http://url/def/hasVersion">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">entiteit</ns1:string>
          <ns1:string key="entiteitUuid">cb020428-ec25-44f7-8add-7e334eb2a3c0</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
    <ns1:map key="https://w3id.org/def/basicsemantics-owl#describes">
      <ns1:array key="eigenschappen">
        <ns1:map>
          <ns1:string key="vullingType">entiteit</ns1:string>
          <ns1:string key="entiteitUuid">004ed20d-1292-4210-a541-755754497fbe</ns1:string>
        </ns1:map>
        <ns1:map>
          <ns1:string key="vullingType">entiteit</ns1:string>
          <ns1:string key="entiteitUuid">004ed20d-1292-4210-a541-755754497fba</ns1:string>
        </ns1:map>
      </ns1:array>
    </ns1:map>
  </ns1:map>
</ns1:map>

See the key "https://w3id.org/def/basicsemantics-owl#describes" is the one i am trying to group, but it can also be another duplicate key. So i can not pinpoint on a hardcoded value for the key.

I have tried a lot off which i found here and other websites but can't seem to make it work dynamically.

Thx for any help in advance.



Solution 1:[1]

If the structure is known to contain only those ns1:array children as part of an ns1:map then perhaps

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
  version="3.0"
  xmlns:xs="http://www.w3.org/2001/XMLSchema"
  xmlns:fn="http://www.w3.org/2005/xpath-functions"
  exclude-result-prefixes="#all">

  <xsl:output method="xml" indent="yes"/>
  
  <xsl:template match="fn:map[fn:map/fn:array[@key = 'eigenschappen']]">
    <xsl:copy>
      <xsl:apply-templates select="@*"/>
      <xsl:for-each-group select="fn:map" group-by="@key">
        <xsl:copy>
          <xsl:apply-templates select="@*"/>
          <xsl:copy select="fn:array[@key = 'eigenschappen']">
            <xsl:apply-templates select="@*, current-group()/fn:array/*"/>
          </xsl:copy>
        </xsl:copy>
      </xsl:for-each-group>
    </xsl:copy>
  </xsl:template>

  <xsl:mode on-no-match="shallow-copy"/>

</xsl:stylesheet>

suffices.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Martin Honnen