0

I referred to an old thread of mine because I have a similar problem to this one: XSLT 1.0: rename elements with same content

I have the following XML source. Within each Item Element I have children that could have the same value, for example in the 3rd Item I have two children with values "ZA SOUTH AFRICA" and "SPAR WC". These I have to "make unique" with a suffix, for example a counter number.

This is the source:

<?xml version="1.0" encoding="UTF-8"?>
<EntityGroup>
<Item>
    <ENTITY_GROUP_CODE>0000004644</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA GROCERY</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>CHECKERS</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>OK KZN</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5/>
</Item>
<Item>
    <ENTITY_GROUP_CODE>0000004612</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA GROCERY</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>SPAR</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>SPAR WC</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5/>
</Item>
<Item>
    <ENTITY_GROUP_CODE>0000056016</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA SOUTH AFRICA</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>SPAR</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>SPAR WC</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5>SPAR WC</ENTITY_GROUP_LEVEL5>
</Item>
<Item>
    <ENTITY_GROUP_CODE>0000056020</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA GROCERY</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>SPAR</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>SPAR WC</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5>SUPERSPAR WC</ENTITY_GROUP_LEVEL5>
</Item>
</EntityGroup>

I came up with this XSLT:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">

<xsl:output encoding="UTF-8" method="xml" indent="yes"/>

<xsl:template match="@*|node()">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()"/>
    </xsl:copy>
</xsl:template>

<xsl:template match="Item">
    <Item>
        <xsl:apply-templates select="@*|node()">
            <xsl:with-param name="number">
                <xsl:number/>
            </xsl:with-param>
        </xsl:apply-templates>
    </Item>
</xsl:template>

<xsl:template match="Item/child::*">
    <xsl:param name="number"/>
    <xsl:element name="{local-name()}">
        <xsl:value-of select="concat(.,'-',count(preceding-sibling::*[. = current()]))"/>   
    </xsl:element>
</xsl:template>

</xsl:stylesheet>

It gives this output:

<?xml version="1.0" encoding="UTF-8"?>
<EntityGroup>
<Item>
    <ENTITY_GROUP_CODE>0000004644-0</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA-0</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA GROCERY-0</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>CHECKERS-0</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>OK KZN-0</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5>-0</ENTITY_GROUP_LEVEL5>
</Item>
<Item>
    <ENTITY_GROUP_CODE>0000004612-0</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA-0</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA GROCERY-0</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>SPAR-0</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>SPAR WC-0</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5>-0</ENTITY_GROUP_LEVEL5>
</Item>
<Item>
    <ENTITY_GROUP_CODE>0000056016-0</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA-0</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA SOUTH AFRICA-1</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>SPAR-0</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>SPAR WC-0</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5>SPAR WC-1</ENTITY_GROUP_LEVEL5>
</Item>
<Item>
    <ENTITY_GROUP_CODE>0000056020-0</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA-0</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA GROCERY-0</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>SPAR-0</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>SPAR WC-0</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5>SUPERSPAR WC-0</ENTITY_GROUP_LEVEL5>
</Item>
</EntityGroup>

But I am expecting this output - please pay attention to the 3rd Item element. I only want duplicate values within Item elements to be with a suffix:

<?xml version="1.0" encoding="UTF-8"?>
<EntityGroup>
<Item>
    <ENTITY_GROUP_CODE>0000004644</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA GROCERY</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>CHECKERS</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>OK KZN</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5/>
</Item>
<Item>
    <ENTITY_GROUP_CODE>0000004612</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA GROCERY</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>SPAR</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>SPAR WC</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5/>
</Item>
<Item>
    <ENTITY_GROUP_CODE>0000056016</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA SOUTH AFRICA-1</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>SPAR</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>SPAR WC</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5>SPAR WC-1</ENTITY_GROUP_LEVEL5>
</Item>
<Item>
    <ENTITY_GROUP_CODE>0000056020</ENTITY_GROUP_CODE>
    <ENTITY_GROUP_LEVEL1>ZA SOUTH AFRICA</ENTITY_GROUP_LEVEL1>
    <ENTITY_GROUP_LEVEL2>ZA GROCERY</ENTITY_GROUP_LEVEL2>
    <ENTITY_GROUP_LEVEL3>SPAR</ENTITY_GROUP_LEVEL3>
    <ENTITY_GROUP_LEVEL4>SPAR WC</ENTITY_GROUP_LEVEL4>
    <ENTITY_GROUP_LEVEL5>SUPERSPAR WC</ENTITY_GROUP_LEVEL5>
</Item>
</EntityGroup>
Nimantha
  • 6,405
  • 6
  • 28
  • 69
Peter
  • 1,786
  • 4
  • 21
  • 40

1 Answers1

0

Almost you are near the results, just change as given:

<xsl:template match="Item/child::*">
<xsl:choose>
    <xsl:when test="preceding-sibling::*[. = current()] and not(current()='')">
        <xsl:element name="{local-name()}">
            <xsl:value-of select="concat(.,'-',count(preceding-sibling::*[. = current()]))"/>   
        </xsl:element>
    </xsl:when>
        <xsl:otherwise>
            <xsl:copy><xsl:apply-templates select="@*|node()"/></xsl:copy>
        </xsl:otherwise>
</xsl:choose>
</xsl:template>
Rudramuni TP
  • 1,268
  • 2
  • 16
  • 26
  • Thank you Rudramuni, it works well. I only added "" to check on empty elements. For empties the logic must not be applied. Best regards, – Peter Nov 05 '14 at 07:59
  • Welcome Peter, nice logical code u coded, now it will be complete one. I edited my answer. – Rudramuni TP Nov 05 '14 at 09:30