Search code examples
xmlxpathxquerybasex

XQuery get distinct values


Im new to XQuery and are trying to learn how to use it with BaseX.

I have this xml containing multiple elements of program:

<program id="4565">
        <name>Musiken i P3</name>
        <url>http://sverigesradio.se/sida/default.aspx?programid=4565</url>
        <editor>Anna-Karin Larsson</editor>
        <channel>164</channel>
        <category>5</category>
</program>

So far i have understod that i can get the distinct values of for example editor like such:

let $vals := $sr/sr/programs/program/editor
let $uniqe-items := distinct-values($vals)

for $vals in $uniqe-items
    order by $vals
    return <li>{string($vals)}</li>

However when i do this I only get the editors name and I can't understand how i also check something like this:

 let $vals := $sr/sr/programs/program/editor
 let $uniqe-items := distinct-values($vals)

 for $vals in $uniqe-items
     where $vals/channel = "132"
     order by $vals
     return <li>{string($vals)}</li>

I was thinking that i could do something like $vals/../channel to get back to the channel attribute but that doesn't seem to be the case.


Solution

  • Please try the following solution. I am using BaseX 9.5

    The distinct-values() gives a sequence of strings: Anna-Karin Larsson, Anna Karenina, not the XML elements.

    It is possible to eliminate where clause completely by using XPath predicate in the for clause:

    for $vals in distinct-values(./programs/program[channel = "132"]/editor)
    

    XQuery

    xquery version "3.1";
    
    declare context item := document {
    <programs>
        <program id="4565">
            <name>Musiken i P3</name>
            <url>http://sverigesradio.se/sida/default.aspx?programid=4565</url>
            <editor>Anna-Karin Larsson</editor>
            <channel>164</channel>
            <category>5</category>
        </program>
        <program id="4770">
            <name>Musiken i P3</name>
            <url>http://sverigesradio.se/sida/default.aspx?programid=4565</url>
            <editor>Anna Karenina</editor>
            <channel>132</channel>
            <category>55</category>
        </program>
    </programs>  
    };
    
    <ul>
    {
      for $vals in distinct-values(./programs/program[channel = "132"]/editor)
      (:where ./programs/program[editor = $vals]/channel = "132":)
      order by $vals
      return <li>{data($vals)}</li>
    }
    </ul>
    

    Output

    <ul>
      <li>Anna Karenina</li>
    </ul>