Это преобразование :
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="contactGrp">
<xsl:copy>
<xsl:apply-templates select="node()|@*">
<xsl:sort select="@name"/>
</xsl:apply-templates>
</xsl:copy>
</xsl:template>
</xsl:stylesheet>
при применении к предоставленному документу XML:
<contactGrp name="People">
<contactGrp name="Developers">
<customer name="Mike" ></customer>
<customer name="Brad" ></customer>
<customer name="Smith" ></customer>
</contactGrp>
<contactGrp name="QA">
<customer name="John" ></customer>
<customer name="abi" ></customer>
</contactGrp>
</contactGrp>
дает желаемый, правильный результат:
<contactGrp name="People">
<contactGrp name="Developers">
<customer name="Brad" />
<customer name="Mike" />
<customer name="Smith" />
</contactGrp>
<contactGrp name="QA">
<customer name="abi" />
<customer name="John" />
</contactGrp>
</contactGrp>
Примечание : всегда будут получены правильные результаты - независимо от уровня вложенности элементов contactGrp