入力:
<persons>
<person name="John" role="Writer"/>
<person name="John" role="Poet"/>
<person name="Jacob" role="Writer"/>
<person name="Jacob" role="Poet"/>
<person name="Joe" role="Poet"/>
</persons>
期待される出力:
<groups>
<group roles="Wriet, Poet" persons="John, Jacob"/>
<group roles="Poet" persons="Joe"/>
</groups>
上記の例のように、まず個人名でグループ化し、全員の役割を見つける必要があります。複数の人が同じ役割のセットを持っていることがわかった場合 (たとえば、ジョンとジェイコブの両方が作家であり詩人でもある場合)、役割のセットごとにグループ化し、人の名前をリストする必要があります。
Muenchian メソッドや EXSLTset:distinct
などを使用して、グループ化の最初のレベルでこれを行うことができます。
<groups>
<group roles="Wriet, Poet" persons="John"/>
<group roles="Wriet, Poet" persons="Jacob"/>
<group roles="Poet" persons="Joe"/>
</groups>
上記は、XSLT 1.0 と EXSLT を使用して変換されました。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:sets="http://exslt.org/sets" extension-element-prefixes="sets">
<xsl:output method="xml" indent="yes" omit-xml-declaration="yes"/>
<xsl:key name="persons-by-name" match="person" use="@name"/>
<xsl:template match="persons">
<groups>
<xsl:for-each select="sets:distinct(person/@name)">
<group>
<xsl:attribute name="persons"><xsl:value-of select="."/></xsl:attribute>
<xsl:attribute name="roles">
<xsl:for-each select="key('persons-by-name', .)">
<xsl:value-of select="@role"/>
<xsl:if test="position()!=last()"><xsl:text>, </xsl:text></xsl:if>
</xsl:for-each>
</xsl:attribute>
</group>
</xsl:for-each>
</groups>
</xsl:template>
</xsl:stylesheet>
ただし、グループ化された役割をグループ化する方法を理解するには助けが必要です。
XSLT 1.0 ソリューションが利用できない場合は、遠慮なく XSLT 2.0 アプローチを推奨してください。