Lucas Weibel
Lucas Weibel

Reputation: 51

XSLT 1 Distinct grouping

I'm trying to do a distinct after a grouping and it doesn't work. Using this node :

<MAIN>
    <VALUE>A</VALUE>
    <VALUE>B</VALUE>
    <VALUE>AB</VALUE>
    <VALUE>A</VALUE>
    <VALUE>AB</VALUE>
</MAIN>

i can use the following xpath :

MAIN/VALUE[not(following::VALUE/text() = text())]

and i have my distinct values B, AB, A. But if i have the following node :

<MAIN>
    <BLOC>
        <TYP>1</TYP>
        <VALUE>A</VALUE>
    </BLOC>
    <BLOC>
        <TYP>1</TYP>
        <VALUE>BA</VALUE>
    </BLOC>
    <BLOC>
        <TYP>1</TYP>
        <VALUE>B</VALUE>
    </BLOC>
    <BLOC>
        <TYP>1</TYP>
        <VALUE>A</VALUE>
    </BLOC>
    <BLOC>
        <TYP>2</TYP>
        <VALUE>A</VALUE>
    </BLOC>
    <BLOC>
        <TYP>2</TYP>
        <VALUE>C</VALUE>
    </BLOC>
</MAIN>

I'm trying to group by TYP before doing the distinct :

MAIN/BLOC[TYP=1]/VALUE[not(following::VALUE/text() = text())]

It doesn't work, i have BA and B but without A.

if i try that :

MAIN/BLOC[TYP=1]/VALUE

the group by return all the values of my TYP.

Why the distinct doesn't work after the grouping ?

Upvotes: 2

Views: 68

Answers (1)

Tim C
Tim C

Reputation: 70638

You need to include the check on TYP=1 in the check on the following node too. At the moment, the second "A" is not being picked up because it does have a following node also of "A"

MAIN/BLOC[TYP=1]/VALUE[not(following::BLOC[TYP=1]/VALUE/text() = text())]

I note that you have tagged this XSLT, and mentioned XSLT in the title. In which case you should be using a technique called Muenchian Grouping to get distinct items.

First, define a key like so

<xsl:key name="blocs_by_value" match="BLOC" use="VALUE" />

Then, to get the distinct VALUE nodes, do this

<xsl:value-of select="MAIN/BLOC[generate-id() = generate-id(key('blocs_by_value', VALUE)[1])]/VALUE" />

For the case that you want to get distinct VALUE nodes for a specific type, define the key like so

<xsl:key name="blocs_by_typ_value" match="BLOC" use="concat(TYP, '|', VALUE)" />

Then, the expression to get distinct values is this...

<xsl:value-of select="MAIN/BLOC[TYP=1][generate-id() = generate-id(key('blocs_by_typ_value', concat(TYP, '|', VALUE))[1])]/VALUE" />

Upvotes: 1

Related Questions