I. This is an XSLT 1.0 conversion :
<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:key name="kEntryByNum" match="logentry" use="substring-before(msg, ':')"/>
<xsl:template match="/*">
<table>
<tr><th>revision</th><th>comment</th></tr>
<xsl:apply-templates select=
"logentry
[generate-id()
=
generate-id(key('kEntryByNum', substring-before(msg, ':'))[1])
]
"/>
</table>
</xsl:template>
<xsl:template match="logentry">
<tr><td colspan="2"><xsl:value-of select="substring-before(msg, ':')"/></td></tr>
<xsl:for-each select="key('kEntryByNum', substring-before(msg, ':'))">
<tr>
<td><xsl:value-of select="@revision"/></td>
<td><xsl:value-of select="msg"/></td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
when applied to the following XML document :
<log>
<logentry revision="1236">
<author>me</author>
<date>2011-11-25T08:28:57.024571Z</date>
<msg>JIRA-5678: commit message</msg>
</logentry>
<logentry revision="1237">
<author>me</author>
<date>2011-11-25T08:28:57.024571Z</date>
<msg>JIRA-5679: commit message</msg>
</logentry>
<logentry revision="1238">
<author>me</author>
<date>2011-11-25T08:28:57.024571Z</date>
<msg>JIRA-5679: commit message</msg>
</logentry>
<logentry revision="1235">
<author>me</author>
<date>2011-11-25T08:28:47.024571Z</date>
<msg>JIRA-5678: - commit2 message</msg>
</logentry>
<logentry revision="1234">
<author>me</author>
<date>2011-11-25T08:28:37.024571Z</date>
<msg>JIRA-5678: commit3 message</msg>
</logentry>
</log>
creates the desired, correct result :
<table>
<tr>
<th>revision</th>
<th>comment</th>
</tr>
<tr>
<td colspan="2">JIRA-5678</td>
</tr>
<tr>
<td>1236</td>
<td>JIRA-5678: commit message</td>
</tr>
<tr>
<td>1235</td>
<td>JIRA-5678: - commit2 message</td>
</tr>
<tr>
<td>1234</td>
<td>JIRA-5678: commit3 message</td>
</tr>
<tr>
<td colspan="2">JIRA-5679</td>
</tr>
<tr>
<td>1237</td>
<td>JIRA-5679: commit message</td>
</tr>
<tr>
<td>1238</td>
<td>JIRA-5679: commit message</td>
</tr>
</table>
II. XSLT 2.0 Solution :
<xsl:stylesheet version="2.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:key name="kEntryByNum" match="logentry" use="substring-before(msg, ':')"/>
<xsl:template match="/*">
<table>
<tr><th>revision</th><th>comment</th></tr>
<xsl:for-each-group select="logentry" group-by="substring-before(msg, ':')">
<xsl:apply-templates select="."/>
</xsl:for-each-group>
</table>
</xsl:template>
<xsl:template match="logentry">
<tr><td colspan="2"><xsl:value-of select="substring-before(msg, ':')"/></td></tr>
<xsl:for-each select="current-group()">
<tr>
<td><xsl:value-of select="@revision"/></td>
<td><xsl:value-of select="msg"/></td>
</tr>
</xsl:for-each>
</xsl:template>
</xsl:stylesheet>
source
share