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:
? : nulla vagy egy elem
+: egy vagy több
*: nulla vagy bármennyi, mindenre illeszkedik
A paraméter típusának( ELEMTÍPUS ) a következő típusokat adhatjuk meg:
node(): bármilyen csomópont lehet
element():
element( ELEM_NEVE ): ez esetben csak az ELEM_NEVE nevű elemek elfogadottak
paraméter nélkül bármilyen elem elfogadott
scheme-element( ELEM_NEVE ): csak egy sémában definiált elem lehet
attribute(): attribútumot fogad el
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
};