Это работа для мюнхенской группировки.Вы найдете многочисленные примеры этого в теге XSLT здесь, в StackOverflow.
Во-первых, вам нужно определить ключ, чтобы помочь вам сгруппировать группы
<xsl:key name="groups" match="group" use="."/>
Это будет искать group элементы для данного имени группы.
Далее необходимо сопоставить все вхождения первого экземпляра каждого имени группы distince.Это делается с помощью этого страшно выглядящего оператора
<xsl:apply-templates select="element/group[generate-id() = generate-id(key('groups', .)[1])]"/>
, т. Е. Сопоставления элементов группы, которые являются первым вхождением этого элемента в наш ключ.
Когда вы сопоставили отдельные узлы группы,Затем вы можете перебрать все другие узлы группы с тем же именем (где $ currentGroup - это переменная, содержащая имя текущей группы)
<xsl:for-each select="key('groups', $currentGroup)">
Если положить это в целом, то получится
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:key name="groups" match="group" use="."/>
<xsl:template match="/root">
<root>
<xsl:apply-templates select="element/group[generate-id() = generate-id(key('groups', .)[1])]"/>
</root>
</xsl:template>
<xsl:template match="group">
<xsl:variable name="currentGroup" select="."/>
<group>
<xsl:attribute name="name">
<xsl:value-of select="$currentGroup"/>
</xsl:attribute>
<xsl:for-each select="key('groups', $currentGroup)">
<element>
<id>
<xsl:value-of select="../id"/>
</id>
<name>
<xsl:value-of select="$currentGroup"/>
</name>
</element>
</xsl:for-each>
</group>
</xsl:template>
</xsl:stylesheet>
Применение этогона вашем примере XML дает следующий результат
<root>
<group name="first">
<element>
<id>1</id>
<name>first</name>
</element>
<element>
<id>3</id>
<name>first</name>
</element>
</group>
<group name="seccond">
<element>
<id>2</id>
<name>seccond</name>
</element>
</group>
</root>