Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Removing duplicates in xml with xslt

I need to remove duplicates in the following xml:

<ListOfRowIDWithListOfBooks xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/">
  <RowIDWithListOfBooks>
    <Row_ID>ADOA-XssK</Row_ID>
    <ListOfBookInfo>
      <book>
        <BookType>Brand</BookType>
        <BookName>jon</BookName>
      </book>
      <book>
        <BookType>Brand</BookType>
        <BookName>jon</BookName>
      </book>
    </ListOfBookInfo>
  </RowIDWithListOfBooks>
</ListOfRowIDWithListOfBooks>

Can anybody help?

like image 606
Steph Avatar asked Jul 20 '11 20:07

Steph


2 Answers

This task can be easily achieved using standard grouping solutions. Do not use single select statements to do that which are well known to cause performance problems.

Note The reference to identity.xsl just include into the stylesheet the well known identity transformation template.

[XSLT 1.0]

<xsl:stylesheet version="1.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:key name="k-books" match="book" use="concat(BookType,'|',BookName)"/>

    <xsl:include href="identity.xsl"/>

    <xsl:template match="ListOfBookInfo">
        <ListOfBookInfo>
            <xsl:copy>
                <xsl:apply-templates select="book
                [generate-id()
                =generate-id(key('k-books',concat(BookType,'|',BookName))[1])]"/>
            </xsl:copy>
        </ListOfBookInfo>
    </xsl:template>

</xsl:stylesheet>

[XSLT 2.0]

<xsl:stylesheet version="2.0" 
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

    <xsl:include href="identity.xsl"/>

    <xsl:template match="ListOfBookInfo">
        <ListOfBookInfo>
            <xsl:for-each-group select="book" 
                group-by="concat(BookType,'|',BookName)">
                <xsl:apply-templates select="."/>
            </xsl:for-each-group>
        </ListOfBookInfo>
    </xsl:template>

</xsl:stylesheet>
like image 148
Emiliano Poggi Avatar answered Oct 17 '22 21:10

Emiliano Poggi


Try this XSLT:

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  <xsl:output method="xml" indent="yes"/>

  <xsl:template match="/">
    <xsl:apply-templates select="//ListOfBookInfo/book[not(BookType = preceding-sibling::book/BookType
                         and BookName = preceding-sibling::book/BookName)]"/>
  </xsl:template>

  <xsl:template match="book">
    <xsl:copy-of select="."/>
  </xsl:template>

</xsl:stylesheet>

It will select books with unique BookType and BookName. In your sample result should be:

<book xmlns:bpws="http://schemas.xmlsoap.org/ws/2003/03/business-process/">
        <BookType>Brand</BookType>
        <BookName>jon</BookName>
      </book>
like image 3
Kirill Polishchuk Avatar answered Oct 17 '22 20:10

Kirill Polishchuk