Jaya Krishna
Jaya Krishna

Reputation: 15

How to remove duplicates including the first instance and just include the unique non-repetitive nodes?

I have the below sample XML code with me and the required output. I need to remove the duplicate rows, which is every instance. Can you help me how to achieve this using XSLT 2.0

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Row>
        <Company>Xyzz</Company>
        <Account>123567</Account>
        <Amount>223.33</Amount>
    </Row>
    <Row>
        <Company>Xyzz</Company>
        <Account>123567</Account>
        <Amount>223.33</Amount>
    </Row>
    <Row>
        <Company>Xyzz</Company>
        <Account>123567</Account>
        <Amount>223.33</Amount>
    </Row>
    <Row>
        <Company>pror</Company>
        <Account>123567</Account>
        <Amount>423.33</Amount>
    </Row>
    <Row>
        <Company>abcd</Company>
        <Account>123567</Account>
        <Amount>123.33</Amount>
    </Row>
</Root>

Required Output:

<?xml version="1.0" encoding="UTF-8"?>
<Root>
    <Row>
        <Company>pror</Company>
        <Account>123567</Account>
        <Amount>423.33</Amount>
    </Row>
    <Row>
        <Company>abcd</Company>
        <Account>123567</Account>
        <Amount>123.33</Amount>
    </Row>
</Root>

Upvotes: 0

Views: 504

Answers (1)

Martin Honnen
Martin Honnen

Reputation: 167446

Grouping in XSLT 2 and 3 is done using xsl:for-each-group (https://www.w3.org/TR/xslt-30/#element-for-each-group), so select="Row" as the grouping population, decide which grouping key you want, if you want to use all child element values as a composite grouping key you use xsl:for-each-group select="Row" composite="yes" group-by="*" in XSLT 3; inside the for-each-group you then have access to the current-group() and can only output (or in generally process) its first and only item if there is only one item in the group by selecting .[not(tail(current-group()))] as . represents the first item in the group and not(tail(current-group())) will be true if there is no second item in the group:

<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
    xmlns:xs="http://www.w3.org/2001/XMLSchema"
    exclude-result-prefixes="#all"
    version="3.0">

  <xsl:output indent="yes"/>

  <xsl:mode on-no-match="shallow-copy"/>

  <xsl:template match="Root">
      <xsl:copy>
          <xsl:for-each-group select="Row" composite="yes" group-by="*">
              <xsl:apply-templates select=".[not(tail(current-group()))]"/>
          </xsl:for-each-group>
      </xsl:copy>
  </xsl:template>

</xsl:stylesheet>

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

Upvotes: 1

Related Questions