_2,_3…, and also a text with "CHECK IT" and so on every time the element "batch" has the same text (except for the first one), I have already an XSLT who can (almost) do that but the problem is that the suffix it add is the position of the element, and it also adds the suffix to the first element, and I need that the first element does not have this suffix nor the text,
This is the input XML that I have :
<ROOT>
<MOTORS>
<ELEMENT>
<NUMBER>
<BATCH>ELEC_KN</BATCH>
</NUMBER>
</ELEMENT>
<ELEMENT>
<NUMBER>
<BATCH>ELEC_LJ</BATCH>
</NUMBER>
</ELEMENT>
<ELEMENT>
<NUMBER>
<BATCH>DIESEL_ZT</BATCH>
</NUMBER>
</ELEMENT>
<ELEMENT>
<NUMBER>
<BATCH>ELEC_LJ</BATCH>
</NUMBER>
</ELEMENT>
<ELEMENT>
<NUMBER>
<BATCH>DIESEL_ZT</BATCH>
</NUMBER>
</ELEMENT>
<ELEMENT>
<NUMBER>
<BATCH>DIESEL_ZT</BATCH>
</NUMBER>
</ELEMENT>
</MOTORS>
</ROOT>
This is my XSLT :
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" indent="yes"/>
<xsl:template match="/">
<Before_sale>
<xsl:for-each select="//ROOT/MOTORS/ELEMENT">
<xsl:variable name="BATCH">
<xsl:value-of select="normalize-space(NUMBER/BATCH)"/>
</xsl:variable>
<xsl:variable name="nameCount" select="count(//ELEMENT[NUMBER/BATCH/text() = current()/NUMBER/BATCH/text()])"/>
<xsl:variable name="REPEAT">
<xsl:choose>
<xsl:when test="$nameCount > 1">
<xsl:value-of select="$BATCH"/>
<xsl:text>_</xsl:text>
<xsl:number count="//ELEMENT[NUMBER/BATCH/text() = current()/NUMBER/BATCH/text()]" level="any"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$BATCH"/>
</xsl:otherwise>
</xsl:choose>
</xsl:variable>
<MOTOR No_ID="{$REPEAT}">
<xsl:if test="$REPEAT != $BATCH">
<xsl:text> CHECK IT </xsl:text>
</xsl:if>
</MOTOR>
</xsl:for-each>
</Before_sale>
</xsl:template>
</xsl:stylesheet>
And this is the output I want (The comments are only to better explain what I need to accomplish.) :
<Before_sale>
<MOTOR No_ID="ELEC_KN"/>
<MOTOR No_ID="ELEC_LJ"></MOTOR> <!-- Even if repeated elements are found later, this one, being the first one, does not have to have the suffix or the check text. -->
<MOTOR No_ID="DIESEL_ZT"> CHECK IT </MOTOR> <!-- Even if repeated elements are found later, this one, being the first one, does not have to have the suffix or the check text. -->
<MOTOR No_ID="ELEC_LJ_1"> CHECK IT </MOTOR> <!--This is the first time that an element with this same text has been found, so I am adding 1-->
<MOTOR No_ID="DIESEL_ZT_1"/> <!--This is the first time that an element with this same text has been found, so I am adding 1-->
<MOTOR No_ID="DIESEL_ZT_2"> CHECK IT </MOTOR> <!--This is the second time that an element with this same text has been found, so I am adding 2-->
</Before_sale>
>Solution :
With XSLT 3 you can easily do
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="3.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/*">
<Before_sale>
<xsl:apply-templates select="//ELEMENT/NUMBER/BATCH"/>
</Before_sale>
</xsl:template>
<xsl:key name="batch" match="ELEMENT/NUMBER/BATCH" use="."/>
<xsl:template match="ELEMENT/NUMBER/BATCH[. is key('batch', .)[1]]">
<MOTOR No_ID="{translate(., ' ', '_')}"/>
</xsl:template>
<xsl:template match="ELEMENT/NUMBER/BATCH[not(. is key('batch', .)[1])]">
<MOTOR>
<xsl:attribute name="NO_ID" expand-text="yes">{translate(., ' ', '_')}_{index-of(key('batch', .)/generate-id(), generate-id(current())) - 1}</xsl:attribute>
<xsl:text> CHECK IT </xsl:text>
</MOTOR>
</xsl:template>
</xsl:stylesheet>
XSLT 3 is supported on lots of platforms like Java, .NET, C/C++, JavaScript , Python)through the various editions and versions of Saxon (e.g. Saxon Java, Saxon .NET, SaxonCS, SaxonJS, SaxonC, Py packages saxonhec).
The XSLT 1.0 version is
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:output method="xml" indent="yes" />
<xsl:template match="/*">
<Before_sale>
<xsl:apply-templates select="//ELEMENT/NUMBER/BATCH"/>
</Before_sale>
</xsl:template>
<xsl:key name="batch" match="ELEMENT/NUMBER/BATCH" use="."/>
<xsl:template match="ELEMENT/NUMBER/BATCH[generate-id() = generate-id(key('batch', .)[1])]">
<MOTOR No_ID="{translate(., ' ', '_')}"/>
</xsl:template>
<xsl:template match="ELEMENT/NUMBER/BATCH[generate-id() != generate-id(key('batch', .)[1])]">
<xsl:variable name="current" select="."/>
<MOTOR>
<xsl:attribute name="NO_ID">
<xsl:value-of select="translate(., ' ', '_')"/>
<xsl:text>_</xsl:text>
<xsl:for-each select="key('batch', .)">
<xsl:if test="generate-id() = generate-id($current)">
<xsl:value-of select="position() - 1"/>
</xsl:if>
</xsl:for-each>
</xsl:attribute>
<xsl:text> CHECK IT </xsl:text>
</MOTOR>
</xsl:template>
</xsl:stylesheet>