Az eddigiek során már számtalan módot láttunk arra, hogy miként lehet elérni a csomópontokat. Az XQuery ezen felül támogatja még csomópontok dinamikusan (futási időben) történő létrehozását is. Nagyon fontos kiemelni a már korábban is említett csomópont identitást újra, mert amit egy konstruktor létrehoz az új azonosítóval fog rendelkezni.
Miután az XQuery esetén az elemszekvenciák mindig kiegyenesítődnek, csak ezen konstruktorok segíthetnek a hierarchikus adatok előállításában. ( Ez egyben alkalmassá is teszi arra, hogy esetlegesen XSLT transzformációkat váltsunk ki XQuery segítségével. ) Az XQuery a hét csomópont típusnak megfelelően hét különböző konstruktorral rendelkezik. Mindegyik esetében létezik
direkt konstruktor: szintaxisuk teljesen megegyezik az XML natív szintaxisával. Bármely jól formázott XML töredék egyben egy érvényes XQuery kifejezés is. (az egyetlen megjegyzés, hogy a CDATA szakaszok szöveges csomópontokká válnak, ezt nem őrzi meg)
kiértékelt konstruktor: kulcsszó vezeti be és mind a neve, mind az értéke dinamikusan számítható az új csomópontnak.
A legjelentősebb konstruktorok:
dokumentum: egy teljesen új XML dokumentum létrehozása
(document {})
document {
<book year="1977">
<title>Harold and the Purple Crayon</title>
<author><last>Johnson</last><first>Crockett</first></author>
<publisher>HarperCollins Juvenile Books</publisher>
<price>14.95</price>
</book>
} Ügyeljünk arra, hogy létező XML dokumentumoknál mindig van
egy láthatatlan document gyökér elem. Ha csak XML
töredékekkel dolgozunk, akkor ennek szerepét a legkülső elem
tölti be, azaz egy <x><y/></x>/*
kifejezés csak egy <y/> elemet
eredményez.
elem:
egy új elem létrehozása történhet direkt módon:
<x><![CDATA[foo & bar]]></x> ≡ <x>foo & bar</x> // a CDATA nem őrződik meg
Az elem neve konstans, de a tartalma mindazonáltal
lehet dinamikusan kiértékelhető. Ezt XQuery-ben a a
{} közé fogott kifejezéssel adhatjuk
meg. A dinamikus konstrukciók menet közben
kiértékelődnek, szemben a közvetlenül megadottakkal,
melyek viszont nem.
Azaz:
<tag>3*3</tag> eredménye pontosan az lesz amit írtunk: <tag>3*3</tag>
ellenben ha dinamikus konstrukciót használunk:
<tag>{3*3}</tag> az eredmény: <tag>9</tag>Fontos megjegyezni, hogy ezek ugyan egymásba ágyazhatóak, de ha erre nem figyelünk, akkor könnyen túlsiklunk azon, hogy egy dinamikus konstruktoron belül már újabb kiértékelésbe nem kezd bele, azaz:
<tag>{<int>3*3</int>}</tag> csupán egy <int>3*3</int> rész eredményez.
Ha ezt tovább akarjuk vinni, akkor az alábbi módon tehetjük:
<tag>{
<int> {
let $x:=3
return $x*$x
}
</int>}
</tag>
A kórházi példánál maradva:
for $p in /persons/person
return <newPerson>
{
let $info := $p/information/personalInformation
return
{
<name>{ data($info/name) }</name>,
<birthDate>{ data($info/birthDate) }</birthDate>
}
}
</newPerson>A második dinamikus kifejezésben felsoroltuk az új
csomópontokat vesszővel elválasztva, amivel egy
csomópontokból álló szekvenciát adunk meg. Ezen
csomópontokon belül viszont már újabb elemekre nincs
szükségünk, ezért az adott információhoz nem magát a
csomópontot kértük vissza, hanem csak a tartalmazott
adatot, amelyet a data függvény
segítségével nyertünk ki a csomópontból.
dinamikusan létrehozva:
element {kifejezés_névhez} {kifejezés_értékhez
}
element { string-join(("foo","bar"),"-") } { 40+2 } => <foo-bar>42</foo-bar>Ez a konstrukció igazán jól alátámasztja, hogy valóban felhasználható az XQuery az XSLT bizonyos fokú kiváltására. Például egy szótár segítségével a dokumentumban használt elemneveket lecseréljük a célnyelvnek megfelelően:
// a szótár
<entry word="address">
<variant lang="de">Adresse</variant>
<variant lang="it">indirizzo</variant>
</entry>
// és ahogy lecseréljük az elemneveket megőrizve a tartalmát (+ attribútumait):
element
{ $dict/entry[@word=name($e)]/variant[lang="it"] }
{ $e/@*, $e/node() }attribútum:
közvetlen módon:
<x a="{(4,2)}"/> => <x a="4 2"/>dinamikusan létrehozva:
attribute {kifejezés_névhez} {kifejezés_értékhez
}
element book {
attribute year { 1977 },
element author {
element first { "Crockett" },
element last { "Johnson" }
},
element publisher {"HarperCollins Juvenile Books"},
element price { 14.95 }
}szöveg
közvetlen módon: karakterek az elem tartalmában vagy CDATA szekcióval. Az elem szöveges értékének meghatározása a szokásos atomizáción megy végig, melyeket sztringgé konvertál és szóköz segítségével összefűz.
dinamikusan:
text {kifejezés}
if (empty(e))
then ()
else text { string-join(for $i in data(e)
return string($i)," ") }
A dinamikus konstruktorok közül az elem konstruktor a legrugalmasabb. A tartalmat megadó szekvencia elemei bármilyen csomóponttípusba tartozhatnak. Az összeállítás során az alábbiakat végzi el a feldolgozó:
egymást követő karakter literálok egy szöveges csomóponttá válnak.
a dinamikus részek kiértékelődnek: {}
a szomszédos atomi értékek sztringgé konvertálódnak és szóköz segítségével összefűzésre kerülnek
a másolt csomópontok tartalommal együtt másolásra kerülnek és új identitást kapnak
szomszédos szöveges csomópontok összefűzésre kerülnek. Az üresek ("") pedig eldobódnak.
// Tippeljük meg mennyi lesz a kifejezés értéke (azaz mennyi csomópont készül?):
count(
<x>Negyvenkettő{40 + 2}{ "pi",3.1415,<y><z/></y>,("","!")[1] }</x>/node()
)A tartalom létrehozásánál egy dologra kell mindenképp figyelni: jól-formázott tartalomra van szükség. (Azaz nem egyezhet meg attribútumok neve, és meg kell előzniük minden más tartalmat.) Ezen felül akármilyen tartalmat is hozunk létre, az mindig dokumentumsorrendet is jelent.