Reputation: 138261
I'm using client-side XSL-T to generate an index from an XML document. The index looks like this:
<index>
<topic name="A">
<page no="127"/>
</topic>
<topic name="B">
<page no="126"/>
</topic>
<topic name="C">
<page no="125"/>
<page no="128"/>
</topic>
</index>
The XSL-T template looks like this:
<xsl:template match="/index">
<table>
<xsl:for-each select="topic/page">
<xsl:sort select="@no"/>
<tr>
<td><xsl:value-of select="@no"/></td>
<td><xsl:value-of select="../@name"/></td>
</tr>
</xsl:for-each>
</table>
</xsl:template>
This sorts the <index>
by page number and displays a table row for each page and topic. However, I found that sometimes my input has duplicate pages:
<index>
<topic name="A">
<page no="126"/>
</topic>
<topic name="B">
<page no="126"/>
</topic>
</index>
In that case, I still want to output one row for each duplicate topic and page, but I'd like to print a number next to the page number to indicate that it's a second occurence. I'd like my output to look like this:
<table>
<tr>
<td>126</td>
<td>Topic A</td>
</tr>
<tr>
<td>126 (1)</td>
<td>Topic B</td>
</tr>
</table>
Unfortunately, I can't nail down a way to tell that I'm on the second occurrence of the page number. I can't use preceding-sibling
because it gives me the preceding input sibling, which is not sorted. Is there a way to do this?
Upvotes: 2
Views: 68
Reputation: 167726
It sounds like a grouping problem you can solve in XSLT 1 with a key and Muenchian grouping http://www.jenitennison.com/xslt/grouping/muenchian.html:
<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="html" indent="yes" doctype-system="about:legacy-compat"/>
<xsl:key name="dup" match="page" use="@no"/>
<xsl:template match="/index">
<table>
<xsl:for-each select="topic/page[generate-id() = generate-id(key('dup', @no)[1])]">
<xsl:sort select="@no"/>
<xsl:for-each select="key('dup', @no)">
<tr>
<td>
<xsl:value-of select="@no"/>
<xsl:if test="position() > 1">
<xsl:value-of select="concat(' (', position(), ') ')"/>
</xsl:if>
</td>
<td><xsl:value-of select="../@name"/></td>
</tr>
</xsl:for-each>
</xsl:for-each>
</table>
</xsl:template>
</xsl:stylesheet>
http://xsltfiddle.liberty-development.net/948Fn5g
Upvotes: 2