Salta el contingut

XQuery

Qué és XQuery?

XQuery és un llenguatge de consulta per a dades XML, estandarditzat pel W3C. La seva expressió fonamental és la FLWOR (pronunciat "flower"):

For – Let – Where – Order by – Return

XQuery és a XML el que SQL és a les bases de dades relacionals.

Estructura FLWOR

(: Sintaxi bàsica :)
for $var in expressió_xpath
let $var := valor
where condició
order by expressió
return resultat

Exemple bàsic

(: Retorna tots els títols de la biblioteca :)
for $ll in doc("biblioteca.xml")//llibre
return $ll/titol
(: Retorna títols ordenats, en format HTML :)
<llista>
{
  for $ll in doc("biblioteca.xml")//llibre
  order by $ll/titol
  return <item>{ string($ll/titol) }</item>
}
</llista>

Clàusula FOR

Itera sobre un conjunt de nodes:

(: Tots els llibres :)
for $ll in doc("biblioteca.xml")//llibre
return $ll

(: Múltiples variables (producte cartesià) :)
for $ll in doc("biblioteca.xml")//llibre
for $au in $ll/autor
return concat($ll/titol, " - ", $au/cognom)

Clàusula LET

Assigna un valor a una variable (no itera):

let $biblioteca := doc("biblioteca.xml")
let $total := count($biblioteca//llibre)
return <total>{ $total }</total>

(: Combinat amb FOR :)
for $ll in doc("biblioteca.xml")//llibre
let $preuTotal := $ll/preu * 1.21
return <item isbn="{ $ll/@isbn }">
    <titol>{ string($ll/titol) }</titol>
    <preuIVA>{ $preuTotal }</preuIVA>
</item>

Clàusula WHERE

Filtra els resultats:

(: Llibres en català :)
for $ll in doc("biblioteca.xml")//llibre
where $ll/@idioma = "ca"
return $ll/titol

(: Múltiples condicions :)
for $ll in doc("biblioteca.xml")//llibre
where $ll/preu > 10 and $ll/preu < 30
return concat($ll/titol, ": ", $ll/preu, " €")

Clàusula ORDER BY

(: Ordenar per preu ascendent :)
for $ll in doc("biblioteca.xml")//llibre
order by xs:decimal($ll/preu) ascending
return <item>{ string($ll/titol) }  { string($ll/preu) } </item>

(: Ordenar per múltiples criteris :)
for $ll in doc("biblioteca.xml")//llibre
order by $ll/@idioma ascending, xs:decimal($ll/preu) descending
return $ll

Condicionals

(: if-then-else :)
for $ll in doc("biblioteca.xml")//llibre
return
    if ($ll/preu > 20)
    then <car>{ string($ll/titol) }</car>
    else <assequible>{ string($ll/titol) }</assequible>

Funcions XQuery

(: Funcions agregades :)
count(doc("biblioteca.xml")//llibre)
sum(doc("biblioteca.xml")//preu)
avg(doc("biblioteca.xml")//preu)
min(doc("biblioteca.xml")//preu)
max(doc("biblioteca.xml")//preu)

(: Funcions de cadena :)
string-length($ll/titol)
upper-case($ll/titol)
lower-case($ll/titol)
contains($ll/titol, "Blanc")
substring($ll/titol, 1, 5)

(: Funcions de seqüència :)
distinct-values(doc("biblioteca.xml")//autor/cognom)

Exemple complet

(: Informe de la biblioteca: llibres per idioma amb estadístiques :)
<informe data="{ current-date() }">
{
  for $idioma in distinct-values(doc("biblioteca.xml")//llibre/@idioma)
  let $llibres := doc("biblioteca.xml")//llibre[@idioma = $idioma]
  order by $idioma
  return
    <grup idioma="{ $idioma }" total="{ count($llibres) }">
    {
      for $ll in $llibres
      order by $ll/titol
      return
        <llibre isbn="{ $ll/@isbn }">
          <titol>{ string($ll/titol) }</titol>
          <autor>{ string($ll/autor/cognom) }</autor>
          <preu>{ string($ll/preu) }</preu>
        </llibre>
    }
    <total_preu>{ sum($llibres/preu) }</total_preu>
    </grup>
}
</informe>

Miniactivitat AC03743

Executa les consultes XQuery sobre biblioteca.xml a BaseX (pot ser via Docker). Escriu una consulta FLWOR que: filtra els llibres d'un idioma determinat, ordena per any, i retorna un HTML amb taula.