Is it possible to match only the first occurrence of a value in an XML doc using XSL transforms?
I'd like to print out every value inside f2 but only the first instance of the contents of f1.
XML Data
<doc>
<datum>
<f1>A</f1>
<f2>Monday</f2>
</datum>
<datum>
<f1>A</f1>
<f2>Tuesday</f2>
</datum>
<datum>
<f1>B</f1>
<f2>Wednesday</f2>
</datum>
</doc>
Output
A
-Monday
-Tuesday
B
-Wednesday
I. This is the well-known Muenchian Grouping method for XSLT 1.0:
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:key name="kDatumByF1" match="datum" use="f1"/>
<xsl:template match=
"datum[generate-id() = generate-id(key('kDatumByF1', f1)[1])]">
<xsl:value-of select="concat('
', f1)"/>
<xsl:apply-templates select="key('kDatumByF1', f1)/f2" mode="inGroup"/>
</xsl:template>
<xsl:template match="f2" mode="inGroup">
- <xsl:value-of select="."/>
</xsl:template>
<xsl:template match="text()"/>
</xsl:stylesheet>
when this transformation is applied on the provided XML document:
<doc>
<datum>
<f1>A</f1>
<f2>Monday</f2>
</datum>
<datum>
<f1>A</f1>
<f2>Tuesday</f2>
</datum>
<datum>
<f1>B</f1>
<f2>Wednesday</f2>
</datum>
</doc>
the wanted, correct result is produced:
A
- Monday
- Tuesday
B
- Wednesday
II. XSLT 2.0 solution, using xsl:for-each-group
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="text"/>
<xsl:template match="/*">
<xsl:for-each-group select="datum" group-by="f1">
<xsl:sequence select="'
', f1"/>
<xsl:apply-templates select="current-group()/f2"/>
</xsl:for-each-group>
</xsl:template>
<xsl:template match="f2">
- <xsl:value-of select="."/>
</xsl:template>
</xsl:stylesheet>