Függvények

A lekérdezések írásánál el tudunk kérni egy szintet, amikor már annyira komplexszé tudnak válni, hogy kényelmesebb az absztrakció egy magasabb fokára lépni. A függvények ebben hivatottak segíteni. Segítségükkel felbonthatjuk a lekérdezéseket és bárhol felhasználhatjuk. Egy XQuery dokumentumban bármennyi függvényt létrehozhatunk, csak arra kell ügyelni, hogy ne legyen névütközés (ezért ne használjuk a beépített függvények fn névterét, és inkább készítsünk sajátot)

Egy függvény definíciójának sémája az alábbi:

declare function NÉVTÉR:FÜGGVÉNY_NEVE( $paraméter1 [ as ELEMTÍPUS[SZÁMOSSÁG] ) ], … ) as TÍPUS { };

A NÉVTÉR nem lehet üres, ha nem szeretnénk sajátot használni, akkor a „local” nevű névteret, mint egy alapértelmezett névteret kell használnunk. A FÜGGVÉNY_NEVE tetszőleges. A paraméterlistában megszabhatjuk hogy milyen ELEMTÍPÚS elemeket várunk. Majd a TÍPUS-ban valamilyen XQuery-ben ismert típust vagy saját típust adunk meg. Az ELEMTÍPUS után a SZÁMOSSÁG-al a paraméter számosságát határozhatjuk meg, azaz egy paraméterhez tartozó csomópontok számát.

Az alábbi számosságokat használhatjuk:

A paraméter típusának( ELEMTÍPUS ) a következő típusokat adhatjuk meg:

Példák függvények használatára:

declare default function namespace "http://www.inf.unideb.hu/FAT/XQuery/functions";

declare function path($n as node()) as xs:string
{ fn:string-join(for $a in $n/ancestor-or-self::*
                    return fn:name($a), "/")
};

declare function reverse($seq)
{ for $i at $p in $seq
    order by $p descending
    return $i
};

// a kórházas példánál maradva 
//a paciensek átlagmagasságának meghatározása
declare function local:avg-height($p as element(persons) ) as xs:double { 
  avg($p/person/information/medicalInformation/height)
};
// adott nevű paciensek keresése
declare function local:filter($persons as element(persons), $filter as xs:string )   as xs:string* {
    $persons/person/information/personalInformation/name[../contains(name,$filter)] 
};

Miután az eddigiek során mindenhol előkerültek a fák, és annak a legtermészetesebb kezelési módja a rekurzió, így lássunk erre is egy egyszerű példát az ős tengely szimulálására:

declare function ancestors($n as node()?) as node()*
{ if (fn:empty($n)) then ()
else (ancestors($n/..), $n/..)
}

és egy összetettet egy részfa összes elemében egy adott attribútum átnevezésére:

declare function local:rplc_attr($n as node(),
                                  $from as xs:string,
                                  $to as xs:string)
{ typeswitch ($n)
    case $e as element() return
        let $a := ($e/@*)[name(.) eq $from]
        return
            element
            { node-name($e) }
            { $e/(@* except $a),
                if ($a) then attribute {$to} {data($a)}
                        else (),
                for $c in $e/node()
                 return local:rplc_attr($c, $from, $to) }
    default return $n
};