XSL 1.0 Replace value and then remove duplicates from xml variable

I'm sorry if this is repetitive, but I am struggling to resolve this. I have a xml variable. I have xsl variable which has xml like this:

<root>
    <data>
        <GroupItems>
            <row id="30" class="A100"/>

            <row id="50" class="B100"/>

            <row id="100" class="A100"/>

            <row id="20" class="C100"/>

        </GroupItems>
    </data>
</root>

I have to replace "id" value from the preceding sibling node based on "class" value. The duplicate preceding class="A100" has to be removed but the "id" value has to be copied to the first occurrence node. In this case required output is:

<root>
    <data>
        <GroupItems>
            <row id="100" class="A100"/>

            <row id="50" class="B100"/>

            <row id="20" class="C100"/>

        </GroupItems>
    </data>
</root>

The below code removing duplicates from the string but I need to replace the id value (id="100" ).

 <xsl:for-each select="CSharp:NodeList($RawInstruction1)//GroupItems/row[(@class = preceding-sibling::row/@class)]">

1 answer

  • answered 2018-11-08 08:01 Martin Honnen

    Start with the identity transformation template and then add a key to "group" the row elements by the class attribute, then you add templates to copy the id attribute from the last row in each group to the first and another template to suppress copying the remaining duplicated rows in a group:

    <?xml version="1.0" encoding="UTF-8"?>
    <xsl:stylesheet
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    
        version="1.0">
    
      <xsl:output method="xml"/>
    
      <xsl:template match="@* | node()">
        <xsl:copy>
          <xsl:apply-templates select="@* | node()"/>
        </xsl:copy>
      </xsl:template>
    
      <xsl:key name="class-group" match="GroupItems/row" use="@class"/>
    
      <xsl:template match="GroupItems/row[generate-id() = generate-id(key('class-group', @class)[1])]/@id">
          <xsl:copy-of select="key('class-group', ../@class)[last()]/@id"/>
      </xsl:template>
    
      <xsl:template match="GroupItems/row[not(generate-id() = generate-id(key('class-group', @class)[1]))]"/>
    
    </xsl:stylesheet>
    

    https://xsltfiddle.liberty-development.net/nc4NzRn