James Taylor
James Taylor

Reputation: 93

XSL removing duplicated elements not working (leaving empty parent)

I have this xml.

<list>
<message ref="00001">
    <entry>
        <orderid>P001</orderid>
        <timestamp>20200109085816092</timestamp>
    </entry>
</message>
<message ref="00002">
    <entry>
        <orderid>P002</orderid>
        <timestamp>20200109085813556</timestamp>
    </entry>
</message>
<message ref="00003">
    <entry>
        <orderid>P003</orderid>
        <timestamp>20200109085814612</timestamp>
    </entry>
</message>
<message ref="00004">
    <entry>
        <orderid>P001</orderid>
        <timestamp>20010109085816092</timestamp>
    </entry>
</message>
<message ref="00005">
    <entry>
        <orderid>P002</orderid>
        <timestamp>20020109085813556</timestamp>
    </entry>
</message>
<message ref="00006">
    <entry>
        <orderid>P003</orderid>
        <timestamp>20030109085814612</timestamp>
    </entry>
</message>

I need to remove "message" nodes when another one with same "orderid" exists (duplicate check). I'm using this xsl.

<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="kOrderId" match="entry" use="orderid"/>

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

<xsl:template match="entry[not(generate-id() = generate-id(key('kOrderId', orderid)[1]))]"/>

But the output holds the unwanted "message" tags (with ref="0004", "0005" and "0006").

<list>
<message ref="00001">
    <entry>
        <orderid>P001</orderid>
        <timestamp>20200109085816092</timestamp>
    </entry>
</message>
<message ref="00002">
    <entry>
        <orderid>P002</orderid>
        <timestamp>20200109085813556</timestamp>
    </entry>
</message>
<message ref="00003">
    <entry>
        <orderid>P003</orderid>
        <timestamp>20200109085814612</timestamp>
    </entry>
</message>
<message ref="00004"/>
<message ref="00005"/>
<message ref="00006"/>

I need to remove these extra tags from the output. How can I achieve it? Thank you.

Upvotes: 0

Views: 34

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 117165

If you want to remove duplicate message elements, then make your key and your template match message, not entry:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output omit-xml-declaration="yes" indent="yes"/>
<xsl:strip-space elements="*"/>

<xsl:key name="kOrderId" match="message" use="entry/orderid"/>

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

<xsl:template match="message[not(generate-id() = generate-id(key('kOrderId', entry/orderid)[1]))]"/>

</xsl:stylesheet>

Note that this assumes a message contains a single entry,

Upvotes: 1

Related Questions