Reputation: 53
this is driving me crazy, for xslt newbie like me.
Input:
<root>
<a><name>kyle</name></a>
<b><name>stan</name></b>
<b><name>wendy</name></b>
<b><name>cece</name></b>
</root>
Expected output:
<root>
<a><name>kyle</name></a>
<b><name>stan</name></b>
</root>
I was asked to return first unique node under 'root', how do I do that?
Either xslt 1.0 or 2.0 is fine.
Thank you so much!!!!
Upvotes: 4
Views: 859
Reputation: 26920
XSLT 2.0 solution :
<?xml version="2.0" encoding="utf-8"?>
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<root>
<xsl:for-each-group select="root/*" group-by="local-name()">
<xsl:copy-of select="."/>
</xsl:for-each-group>
</root>
</xsl:template>
</xsl:stylesheet>
Output:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<a>
<name>kyle</name>
</a>
<b>
<name>stan</name>
</b>
</root>
Upvotes: 1
Reputation: 52848
You can match any element that has a preceding sibling with the same name and not output anything.
Example XSLT:
<xsl:stylesheet version="2.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output indent="yes"/>
<xsl:strip-space elements="*"/>
<xsl:template match="node()|@*">
<xsl:copy>
<xsl:apply-templates select="node()|@*"/>
</xsl:copy>
</xsl:template>
<xsl:template match="/*/*[preceding-sibling::*[name() = current()/name()]]"/>
</xsl:stylesheet>
Output (using Saxon 9 HE):
<root>
<a>
<name>kyle</name>
</a>
<b>
<name>stan</name>
</b>
</root>
Upvotes: 1