To extend the solution for your previous question provided by Rudramuni TP, you can add an additional key to get unique attribute values:
<xsl:key name="kAttribValue" match="@*" use="."/>
and an additional variable:
<xsl:variable name="var2">
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
<xsl:value-of select="concat(name(.), '(', .,')', ' ', count(key('kAttribValue', .)))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
With these adjustments to Rudramuni TPs code:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:key name="kEleName" match="*" use="local-name()"/>
<xsl:key name="kAttribName" match="@*" use="local-name()"/>
<xsl:key name="kAttribValue" match="@*" use="."/>
<xsl:variable name="var1">
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribName', name()))]">
<xsl:value-of select="concat(name(.), ' ', count(key('kAttribName', name(.))))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:variable name="var2">
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
<xsl:value-of select="concat(name(.), '(', .,')', ' ', count(key('kAttribValue', .)))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<xsl:apply-templates select="*[generate-id() = generate-id(key('kEleName', name()))]"/>
</xsl:template>
<xsl:template match="*">
<xsl:if test="position()=1"><xsl:text>For tags: </xsl:text></xsl:if>
<xsl:value-of select="concat(name(.), ' ', count(key('kEleName', name(.))))"/>
<xsl:if test="following-sibling::*">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:if test="position()=last()">
<xsl:text> For attributes: </xsl:text>
<xsl:value-of select="$var2"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
when applied to your input XML
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<cat size="small"/>
</a>
the extended result is generated:
For tags: apple 2, banana 1, sugar 1, cat 1
For attributes: color(red) 1, color(green) 1, color(yellow) 1, taste(sweet) 1, size(small) 1
Update: As mentioned in the comment, above adjustment (as well as the answer for the previous question) only works for an input as provided in the question. Given an input XML like e.g.
<root>
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<cat size="small"/>
</a>
<a>
<apple color="red"/>
<apple color="green"/>
<banana color="yellow"/>
<sugar taste="sweet"/>
<dog size="big"/>
</a>
</root>
the template can be adjusted as follows:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" omit-xml-declaration="yes"/>
<xsl:key name="kEleName" match="*" use="local-name()"/>
<xsl:key name="kAttribName" match="@*" use="local-name()"/>
<xsl:key name="kAttribValue" match="@*" use="."/>
<xsl:variable name="var1">
<xsl:for-each select="//a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
<xsl:value-of select="concat(name(.), ' (', .,')', ' ', count(key('kAttribValue', .)))"/>
<xsl:if test="not(position()=last())">
<xsl:text>, </xsl:text>
</xsl:if>
</xsl:for-each>
</xsl:variable>
<xsl:template match="/*">
<xsl:apply-templates select="a/*[generate-id() = generate-id(key('kEleName', name()))]"/>
</xsl:template>
<xsl:template match="*">
<xsl:if test="position()=1"><xsl:text>For tags: </xsl:text></xsl:if>
<xsl:value-of select="concat(name(.), ' ', count(key('kEleName', name(.))))"/>
<xsl:if test="following::*">
<xsl:text>, </xsl:text>
</xsl:if>
<xsl:if test="position()=last()">
<xsl:text> For attributes: </xsl:text>
<xsl:value-of select="$var1"/>
</xsl:if>
</xsl:template>
</xsl:stylesheet>
When this is applied to the adjusted example input XML this generates the output:
For tags: apple 4, banana 2, sugar 2, cat 1, dog 1
For attributes: color (red) 2, color (green) 2, color (yellow) 2, taste (sweet) 2, size (small) 1, size (big) 1
The adjustments are as follows: This
<xsl:for-each select="/a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
has to be adjusted to
<xsl:for-each select="//a/*/@*[generate-id() = generate-id(key('kAttribValue', .))]">
as otherwise only attributes of children of the first a node are matched.
This
<xsl:apply-templates select="*[generate-id() = generate-id(key('kEleName', name()))]"/>
has to be adjusted to
<xsl:apply-templates select="a/*[generate-id() = generate-id(key('kEleName', name()))]"/>
as otherwise the a tags would be selected (which would produce the output
For tags: a 2,).
And this
<xsl:if test="following-sibling::*">
<xsl:text>, </xsl:text>
</xsl:if>
has to be adjusted to
<xsl:if test="following::*">
<xsl:text>, </xsl:text>
</xsl:if>
as the added dog in the second a node is not a following sibling but still a following element.
It's clear that this adjustment won't work if unknown requirements would allow to have different named parent nodes - as simplified example it won't work for an input like
<a>
<apple color="red"/>
<apple color="green"/>
</a>
<b>
<banana color="yellow"/>
</b>
In case different parent nodes or nested structures like e.g.
<a>
<apple color="red"/>
<apple color="green"/>
<b>
<banana color="yellow"/>
</b>
</a>
should also be handled, I suggest to ask a new question for this as this differs too much from the example input XML as provided in the question.