Reputation:
I'm looking to display a list of same-level node names, without duplicates.
Let's say I have
<a>
<b>
<c />
<d />
<d />
</b>
<b>
<e />
<c />
<f />
</b>
</a>
I'd want c,d,e,f to be displayed. I've found several solutions to a similar problem, eliminating duplicate siblings from output, but I'm having trouble eliminating duplicate "cousins".
Upvotes: 2
Views: 2217
Reputation: 127447
I would use the XPath preceding-sibling axis, and check for same local name. Untested:
<xsl:template match="c|d|e|f">
<xsl:if test="local-name(.) != local-name(preceding-sibling::*[1])">
<xsl:copy-of select="."/>
</xsl:if>
</xsl:template>
IOW, if an element has the same name as its preceding-sibling, it does not get copied.
Upvotes: 0
Reputation: 338118
One possibility:
<!-- make all element nodes accessible by their nesting level -->
<xsl:key name="kNodesByLevel" match="*" use="count(ancestor-or-self::*)" />
<xsl:template match="/">
<!-- select all nodes on one particular level -->
<xsl:variable name="lvl" select="key('kNodesByLevel', 3)" />
<!-- step through them... -->
<xsl:for-each select="$lvl">
<xsl:sort select="name()" />
<xsl:variable name="name" select="name()" />
<!-- ... and group them by node name -->
<xsl:if test="generate-id() = generate-id($lvl[name() = $name][1])">
<xsl:copy-of select="." />
</xsl:if>
</xsl:for-each>
</xsl:template>
Output for the XML you provided:
<c />
<d />
<e />
<f />
Upvotes: 1