GeoffreyB
GeoffreyB

Reputation: 526

Merge 2 variables (lists) and remove duplicates

I have this xml code and I want to select the <e> and <z> values in the whole document and sort them without any duplicates:

<root>
    <a>
        <b>2.7</b>
        <c>
            <d>
                <e>NZ 5222</e>
            </d>
            <d>
                <e>NZ 5223</e>
            </d>
            <d>
                <e>NZ 5224</e>
            </d>
            <d>
                <e>NZ 5225</e>
            </d>
        </c>
    </a>
    <a>
        <b>2.7</b>
        <c>
            <d>
                <e>NZ 5222</e>
            </d>
            <d>
                <e>NZ 611</e>
            </d>
            <d>
                <e>NZ 54</e>
            </d>
            <d>
                <e>NZ 522</e>
            </d>
        </c>
    </a>
    <a>
        <x>
            <y>
                <z>NZ 5222</z>
            </y>
            <y>
                <z>NZ 677</z>
            </y>
        </x>
    </a>
</root>

And this XSL stylesheet:

<xsl:stylesheet version="1.0" 
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output method="xml" version="1.0" encoding="UTF-8" indent="yes"/>
<xsl:template match='/'>
               <xsl:variable name="unique-list" select="//e[ancestor::a/b='2.7' and not(.=following::e)]" />
               <xsl:variable name="unique-list2" select="//z[not(.=following::z)]" />

               <xsl:for-each select="$unique-list">
                    <xsl:value-of select="." />
                    <br/>
               </xsl:for-each>
               <xsl:for-each select="$unique-list2">
                    <xsl:value-of select="." />
                    <br/>
                </xsl:for-each>
</xsl:template>
</xsl:stylesheet>

Output is:

NZ 5222
NZ 5223
NZ 5224
NZ 5225
NZ 5222
NZ 611
NZ 54
NZ 522
NZ 5222
NZ 677

Desired Output with sorting and without any duplicates:

NZ 54
NZ 522
NZ 611
NZ 677
NZ 5222
NZ 5223
NZ 5224
NZ 5225

Upvotes: 0

Views: 165

Answers (1)

michael.hor257k
michael.hor257k

Reputation: 116957

I want to select the <e> and <z> values in the whole document and sort them without any duplicates

I suggest you use the Muenchian grouping method to eliminate duplicates. This is much more efficient than your atttempted method - and sorting will also become fairly trivial (other than the problem of sorting only by the numerical part of the value):

XSLT 1.0

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

<xsl:key name="k" match="e | z" use="." />

<xsl:template match="/root">
    <xsl:for-each select="(a/c/d/e | a/x/y/z)[count(. | key('k', .)[1]) = 1]">
        <xsl:sort select="substring-after(., ' ')" data-type="number" order="ascending"/>
        <xsl:value-of select="." />
        <br/>
    </xsl:for-each>
</xsl:template>

</xsl:stylesheet>

I only want to list <e> item when the child <b> of the ancestor <a> is equal to 2.7

Then change:

<xsl:for-each select="(a/c/d/e | a/x/y/z )[count(. | key('k', .)[1]) = 1]">

to:

<xsl:for-each select="(a[b=2.7]/c/d/e | a/x/y/z )[count(. | key('k', .)[1]) = 1]">

Note that this means "when any child <b> of the ancestor <a> is equal to 2.7".

Upvotes: 1

Related Questions