for-each-group
withを使用した XSLT 2.0 のアプローチを次に示しますgroup-by
。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="events">
<xsl:for-each-group select="event/person" group-by="concat(@first, '|', @last)">
<xsl:copy-of select="."/>
</xsl:for-each-group>
</xsl:template>
</xsl:stylesheet>
変形する
<events>
<event date="2013-06-17">
<person first="Joe" last="Bloggs" />
<person first="John" last="Smith" />
</event>
<event date="2013-01-29">
<person first="Jane" last="Smith" />
<person first="John" last="Smith" />
</event>
<event date="2012-09-03">
<person first="Joe" last="Bloggs" />
<person first="John" last="Doe" />
</event>
<event date="2012-04-05">
<person first="Jane" last="Smith" />
<person first="John" last="Smith" />
<person first="John" last="Doe" />
</event>
</events>
の中へ
<person first="Joe" last="Bloggs"/>
<person first="John" last="Smith"/>
<person first="Jane" last="Smith"/>
<person first="John" last="Doe"/>
XSLT 1.0 を使用すると、
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="by-name" match="event/person" use="concat(@first, '|', @last)"/>
<xsl:template match="events">
<xsl:for-each select="event/person[generate-id() = generate-id(key('by-name', concat(@first, '|', @last))[1])]">
<xsl:copy-of select="."/>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
説明については、 http://www.jenitennison.com/xslt/grouping/muenchian.xmlを参照してください。
Muenchian のグループ化は次のように簡略化できます。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="by-name" match="event/person" use="concat(@first, '|', @last)"/>
<xsl:template match="events">
<xsl:copy-of select="event/person[generate-id() = generate-id(key('by-name', concat(@first, '|', @last))[1])]"/>
</xsl:template>
</xsl:stylesheet>
もちろん、結果ツリーにコピーする代わりにapply-templates
、各グループの最初の項目を次のように変換することもできます。
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:key name="by-name" match="event/person" use="concat(@first, '|', @last)"/>
<xsl:template match="events">
<xsl:apply-templates select="event/person[generate-id() = generate-id(key('by-name', concat(@first, '|', @last))[1])]"/>
</xsl:template>
<xsl:template match="person">
<foo>...</foo>
</xsl:template>
</xsl:stylesheet>
XSLT 2.0 ではfor-each-group
、アイテムを格納する変数を使用する必要があります。
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:template match="events">
<xsl:variable name="first-person-in-groups" as="element(person)*">
<xsl:for-each-group select="event/person" group-by="concat(@first, '|', @last)">
<xsl:copy-of select="."/>
</xsl:for-each-group>
</xsl:variable>
<xsl:apply-templates select="$first-person-in-groups"/>
</xsl:template>
<xsl:template match="person">
<foo>...</foo>
</xsl:template>
</xsl:stylesheet>
そうすれば、一連のperson
要素を使用できますapply-templates
。